Block的定义与声明
定义
1 | ^returnType (args) { functionBody; }; |
如果returnType为void则可以省略:
1 | ^(args) { functionBody; }; |
如果无参数列表args,可以写成void,可以省略,也可以连括号一起省略:
1 | ^returnType (void) { functionmBody; } |
如果返回类型为void且没有参数,则可以省略成:
1 | ^ { functionmBody; } |
声明
1 | returnType (^blockName) ( argTypes ); |
如果argTypes为空(即没有参数),只能用(void)代替,不能进一步省略。
如果作为函数参数,则声明略有不同,如下:
1 | (returnType (^) ( argTypes )) blockName |
举例:
1 | - (void) callback: (int (^)(void))blk; |
Block的用法
Typedef别名
即使用typedef 声明即可,声明中的blockName即为这个block的别名,举例:
1 | typedef int (^blk) (void); |
赋值操作
赋值操作即为声明=定义;
调用
类似函数的调用即可,举例:
1 | typedef int (^blk) (void); |
变量的两种引用形式
不需要改变值
不需要改变值的变量直接使用即可,进行的是值传递,即在定义block之前的值会被传进去。
需要改变值
需要用__block修饰该变量,如果涉及到self,则需要将self转换成weakSelf避免循环引用,即:
1 | __weak __typeof(self)weakSelf = self; |
之后对self的操作都使用weakSelf来操作,如果持有该block的对象被释放,则该weakSelf也会置nil。
p.s. 只有会产生循环引用的情况才需要转换成weakSelf。
而在一个block中,weakSelf随时都可能因为引用它的对象的销毁而置空,因此可以使用再次转为strongSelf的方式,即:
1 | __strong __typeof(self) strongSelf = weakSelf; |
这样就可以防止在block的运行过程中的weakSelf的意外置nil。
Block的用途
枚举
1 | - (void)enumerateObjectsUsingBlock:(void (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx, BOOL *stop))block; |
具体对NSArray中的每一个对象的操作均在block中进行。注意这里的(NSEnumerationOptions)opts 有两个选项:
-
NSEnumerationReverse,逆序访问
-
NSEnumerationConcurrent,同步访问,不保证顺序,但速度较快
UIView动画
参见iOS动画总结-Block动画 中的第一部分,UIView的两种Block动画实现方式。
排序
1 | - (void)sortUsingComparator:(NSComparator NS_NOESCAPE)cmptr; |
这个比较函数的Block,返回类型NSComparisonResult有三个枚举:
-
NSOrderedAscending - obj1 < obj2
-
NSOrderedSame - obj1 = obj2
-
NSOrderedDescending - obj1 > obj2
Completion handler与错误处理
主要是在某些方法中含有Block类型的参数,可以用作completion handler和错误处理。
GCD多线程控制
参见iOS多线程-GCD 中的GCD相关部分