block 的演练和使用

来源:互联网 时间:1970-01-01

动画 block 回顾 self.demoView.center = CGPointMake(self.view.center.x, 0);// 此方法会立即执行动画 block[UIView animateWithDuration:2.0 delay:0 usingSpringWithDamping:0.3 initialSpringVelocity:10 options:0 animations:^{NSLog(@"动画开始");self.demoView.center = self.view.center;} completion:^(BOOL finished) {// 会在动画结束后执行NSLog(@"动画完成");}];NSLog(@"come here"); block 基本演练 最简单的 block - (void)blockDemo1 {// 定义block// 类型 变量名 = 值void (^block)() = ^ {NSLog(@"Hello block");};// 执行block();}

使用 inlineBlock可以快速定义 block,不过 block一定要过关

当作参数传递 - (void)blockDemo2 {void (^block)() = ^ {NSLog(@"Hello block");};[self demoBlock:block];}/// 演示 block 当作参数传递- (void)demoBlock:(void (^)())completion {NSLog(@"干点什么");completion();} 使用局部变量 - (void)blockDemo3 {// 栈区变量int i = 10;NSLog(@"%p", &i);void (^block)() = ^ {// 定义 block 的时候会对栈区变量进行一次 copyNSLog(@"Hello block %d %p", i, &i);};[self demoBlock:block];}

如果 block 中使用了外部变量,会对外部变量做一次 copy

在 block 中修改外部变量 - (void)blockDemo4 {// 栈区变量__block int i = 10;NSLog(@"%p", &i);void (^block)() = ^ {// 定义 block 的时候会对栈区变量进行一次 copyNSLog(@"Hello block %d %p", i, &i);i = 20;};NSLog(@"block 定义完成 %p %d", &i, i);[self demoBlock:block];NSLog(@"===>%d", i);}

如果要在 block 内部修改栈区变量,需要使用 __block修饰符,并且定义 block 之后,栈区变量的地址会变化为堆区地址block 的内存位置

block 的内存位置 全局区:如果block中没有使用任何全局变量 栈区:如果 block 中使用了外部变量 MRC 模式可以看到 ARC 模式,系统会自动将 Block 复制到堆中

堆区:将 block 设置给 copy 属性

@property (nonatomic, copy) void (^myBlock)(); - (void)blockDemo5 {int i = 10;void (^block)() = ^ {NSLog(@"i --- %d", i);};NSLog(@"%@", block);self.myBlock = block;}- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {NSLog(@"%@", self.myBlock);}

注意:虽然目前 ARC 编译器在设置属性时,已经替程序员复制了 block,但是定义 block时,仍然建议使用 copy属性

// 面试题- (void)blockDemo4 {int i = 10;// 提问:输出是几?// 10,定义 block 的时候,10已经被复制到堆中了void (^block)() = ^ {NSLog(@"%d", i);};i = 20;block();}

问:block在哪里?=> 全局区

- (void)blockDemo5 {// 问:block在哪里?=> 全局区// 原因:block 中没有使用任何的外部变量,不会因为任何外部因素而改变// 会保存在全局区void (^block)() = ^ {NSLog(@"hello world");};NSLog(@"%@", block);}

问:block在哪里?=> 堆区

- (void)blockDemo6 {int i = 10;// 问:block在哪里?=> 堆区// 原因:因为用到了外部变量,而block准备好的代码,在`需要的时候`被执行// 调用方并不知道 block 什么时候会被调用// MRC 开发,block 在栈区,因为 MRC 的所有内存管理由程序员负责// ARC 开发,block 之所以在堆区,是因为编译器帮我们实现的// 问:为什么block属性要用 copy?void (^block)() = ^ {NSLog(@"hello %d", i);};NSLog(@"%@", block);// 在定义 block 属性的时候,必须使用 copy,这样在设置数值的时候,可以将栈区的 block 复制到堆中self.myBlock = block;NSLog(@"%@", self.myBlock);} 总结: Block 如果里边没有引用外边的任何变量,在全局区 Block 如果里边引用外边的任何变量,在堆区 MRC 的 Block 在栈区 ARC 的 Block 在堆区


相关阅读:
Top