[0. Brief introduction of block]
Block是iOS4.0+ 和Mac OS X 10.6+ 引进的对C语言的扩展,用来实现匿名函数的特性。
这个解释用到block来也很恰当:一个函数里定义了个block,这个block可以访问该函数的内部变量。
一个简单的Block示例如下:
- int (^maxBlock)(int, int) = ^(int x, int y) { return x > y ? x : y; };
[1. Why block]
Block除了能够定义参数列表、返回类型外,还能够获取被定义时的词法范围内的状态(比如局部变量),并且在一定条件下(比如使用__block变量)能够修改这些状态。此外,这些可修改的状态在相同词法范围内的多个block之间是共享的,即便出了该词法范围(比如栈展开,出了作用域),仍可以继续共享或者修改这些状态。
通常来说,block都是一些简短代码片段的封装,适用作工作单元,通常用来做并发任务、遍历、以及回调。
比如我们可以在遍历NSArray时做一些事情:
- - (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block;
其中将stop设为YES,就跳出循环,不继续遍历了。
而在很多框架中,block越来越经常被用作回调函数,取代传统的回调方式。
- 用block作为回调函数,可以使得程序员在写代码更顺畅,不用中途跑到另一个地方写一个回调函数,有时还要考虑这个回调函数放在哪里比较合适。采用block,可以在调用函数时直接写后续处理代码,将其作为参数传递过去,供其任务执行结束时回调。
- 另一个好处,就是采用block作为回调,可以直接访问局部变量。比如我要在一批用户中修改一个用户的name,修改完成后通过回调更新对应用户的单元格UI。这时候我需要知道对应用户单元格的index,如果采用传统回调方式,要嘛需要将index带过去,回调时再回传过来;要嘛通过外部作用域记录当前操作单元格的index(这限制了一次只能修改一个用户的name);要嘛遍历找到对应用户。而使用block,则可以直接访问单元格的index。
这份文档中提到block的几种适用场合:
- 任务完成时回调处理
- 消息监听回调处理
- 错误回调处理
- 枚举回调
- 视图动画、变换
- 排序