Blocks是一种语言级别的元素,可以将其当成参数值在函数之间传递的代码块。
Blocks是Objective-C对象,因此其可以被添加到集合(NSArray或NSDictionary)中。Blocks像其他语言的闭包一样,可以从包含它的区域范围内取值。
语法
Block的完整写法如下:
1 | double (^add)(double, double) = ^(double a, double b){ |
定义中的参数如果为Void,可以不写,实现中的参数和返回如果是Void,也可以不写:
1 | void (^haha)() = ^{ |
如果想要强调返回值类型,也可以在实现中加上返回值类型:
1 | void (^haha)() = ^void{ |
Block可以作为函数参数传递,如果函数需要多个参数,最好是作为最后一个参数,保证函数的可读性:
1 | - (void)testBlock:(void(^)(void))block{ |
Block还可以作为对象的属性,注意其修饰符是copy,因为其范围已经与其赋值范围不同,所以需要复制其取到的值,关于取值的范围参考下一章节:
1 | @property (copy) void (^blockProperty)(void); |
取值
除了从参数中取值,Blocks还可以从包含它的范围内取值。但是,其取得的值是const属性的,意外着不会改变。例如:
1 | int a = 0; |
打印结果为:
1 | 0 |
如果是指针类型,则其指向的对象地址不变,但是对象的属性是可以发生变化的。
1 | NSMutableArray *abc = [NSMutableArray arrayWithArray:@[@(0)]]; |
打印结果为:
1 | 1 |
如果希望取得的值是可以修改的,可以加上修饰符__block:
1 | __block int a = 0; |
打印结果为:
1 | 1 |
类型
如果需要多个Block沿用同一种语法,可以将其定义为类型:
1 | typedef void(^VoidBlock)(void); |
定义为类型还可以避免可读性极差的Block嵌套:
1 | void (^(^complexBlock)(void (^)(void)))(void) = ^ (void (^aBlock)(void)) { |
引用
Blocks对其取值的对象是保持强引用的,包括self,所以,容易导致循环引用:
1 | self.block = ^{ |
解决办法是,创建一个弱引用:
1 | __weak typeof(self) weakSelf = self; |