高能预警:本篇文章非常长,因为 BlocksKit 的实现还是比较复杂和有意的。这篇文章不是为了剖析 iOS 开发中的 block 的实现以及它是如何组成甚至使用的,如果你想通过这篇文章来了解 block 的实现,它并不能帮到你。
Block 到底是什么?这可能是困扰很多 iOS 初学者的一个问题。如果你在 Google 上搜索类似的问题时,可以查找到几十万条结果,block 在 iOS 开发中有着非常重要的地位,而且它的作用也越来越重要。
概述
这篇文章仅对 BlocksKit v2.2.5 的源代码进行分析,从框架的内部理解下面的功能是如何实现的:
- 为 NSArray、 NSDictionary 和 NSSet 等集合类型以及对应的可变集合类型 NSMutableArray、NSMutableDictionary 和 NSMutableSet 添加 bk_each: 等方法完成对集合中元素的快速遍历
- 使用 block 对 NSObject 对象 KVO
- 为 UIView 对象添加 bk_whenTapped: 等方法快速添加手势
- 使用 block 替换 UIKit 中的 delegate ,涉及到核心模块 DynamicDelegate。
BlocksKit 框架中包括但不仅限于上述的功能,这篇文章是对 v2.2.5 版本源代码的分析,其它版本的功能不会在本篇文章中具体讨论。
如何提供简洁的遍历方法
BlocksKit 实现的最简单的功能就是为集合类型添加方法遍历集合中的元素。
1 2 3 |
[@[@1,@2,@3] bk_each:^(id obj) { NSLog(@"%@",obj); }]; |
这段代码非常简单,我们可以使用 enumerateObjectsUsingBlock: 方法替代 bk_each: 方法:
1 2 3 4 5 6 7 |
[@[@1,@2,@3] enumerateObjectsUsingBlock:^(id obj,NSUInteger idx,BOOL *stop) { NSLog(@"%@",obj); }]; 2016-03-05 16:02:57.295 Draveness[10725:453402] 1 2016-03-05 16:02:57.296 Draveness[10725:453402] 2 2016-03-05 16:02:57.297 Draveness[10725:453402] 3 |
这部分代码的实现也没什么难度:
1 2 3 4 5 6 7 8 |
- (void)bk_each:(void (^)(id obj))block { NSParameterAssert(block != nil); [self enumerateObjectsUsingBlock:^(id obj,NSUInteger idx,BOOL *stop) { block(obj); }]; } |
它在 block 执行前会判断传进来的 block 是否为空,然后就是调用遍历方法,把数组中的每一个 obj 传给 block。
BlocksKit 在这些集合类中所添加的一些方法在 Ruby、Haskell 等语言中也同样存在。如果你接触过上面的语言,理解这里方法的功能也就更容易了,不过这不是这篇文章关注的主要内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// NSArray+BlocksKit.h - (void)bk_each:(void (^)(id obj))block; - (void)bk_apply:(void (^)(id obj))block; - (id)bk_match:(BOOL (^)(id obj))block; - (NSArray *)bk_select:(BOOL (^)(id obj))block; - (NSArray *)bk_reject:(BOOL (^)(id obj))block; - (NSArray *)bk_map:(id (^)(id obj))block; - (id)bk_reduce:(id)initial withBlock:(id (^)(id sum,id obj))block; - (NSInteger)bk_reduceInteger:(NSInteger)initial withBlock:(NSInteger(^)(NSInteger result,id obj))block; - (CGFloat)bk_reduceFloat:(CGFloat)inital withBlock:(CGFloat(^)(CGFloat result,id obj))block; - (BOOL)bk_any:(BOOL (^)(id obj))block; - (BOOL)bk_none:(BOOL (^)(id obj))block; - (BOOL)bk_all:(BOOL (^)(id pan class="crayon-t">BOOL)bk_all:(BOOL (^)(id Block 到底是什么?这可能是困扰很多 iOS 初学者的一个问题。如果你在 Google 上搜索类似的问题时,可以查找到几十万条结果,block 在 iOS 开发中有着非常重要的地位,而且它的作用也越来越重要。
概述这篇文章仅对 BlocksKit v2.2.5 的源代码进行分析,从框架的内部理解下面的功能是如何实现的:
BlocksKit 框架中包括但不仅限于上述的功能,这篇文章是对 v2.2.5 版本源代码的分析,其它版本的功能不会在本篇文章中具体讨论。 如何提供简洁的遍历方法BlocksKit 实现的最简单的功能就是为集合类型添加方法遍历集合中的元素。
这段代码非常简单,我们可以使用 enumerateObjectsUsingBlock: 方法替代 bk_each: 方法:
这部分代码的实现也没什么难度:
它在 block 执行前会判断传进来的 block 是否为空,然后就是调用遍历方法,把数组中的每一个 obj 传给 block。 BlocksKit 在这些集合类中所添加的一些方法在 Ruby、Haskell 等语言中也同样存在。如果你接触过上面的语言,理解这里方法的功能也就更容易了,不过这不是这篇文章关注的主要内容。
|