BLOCKS OR DELEGATES

有人曾问了一个精典的问题,我们在回调中使用block还是delegate呢? 在这个问题中,我们先了解一下苹果在遇到这种问题是怎么选择的。我们可以通过官方文档看到在哪些情况下会选择delegate,哪些选择使用了delegate。通过了解苹果的选择,我们可以推导出一些规则。

如何在官方文档中查找

如何在庞大的文档中找出相关的内容呢,delegate我们可以直接搜索“delegate”这个关键词,而block我们不能直接搜索^,当苹果在使用block的时候,会包括以下关键词:Handler, Completion,Block。

1.If an object has more than one distinct event, use delegation.

如果一个对象有多个明确的响应事件,请用delegate.

理解:如果要回调另一个对象时,只有一个方法的时候优先使用block,但是超过一个回调方法的时候,如果继续使用block的话,需要在block里面多传一个type的字段,来对应不同状态处理。但是使用delegate的话,就不用考虑type了,因为可以在发起调用的时候就判断好要调用哪个方法。把选择方法业务最相关的地方。

2.If an object is a singleton, we can't use delegation.

当前对象一个单例的时候,我们就不能再使用delegate

理解:当在多个业务控制器中使用单例,并给这个单例设置不同的delegate时,会导致前面的赋值被覆盖.假如CLLocationManager是一个单例对象(实际上它不是),我们在A页面设置了delegate用来监听位置的变换,如果切换到B页面我们把CLLocationManager的delegate绑定到了B上(B上面也要求监听位置的变换),如果我们再回A的时候,CLLocationManager这个单例对象的delegate现在已绑定在了B的实例上。所以我们就不能用delegate。

3.If the object is calling back for additional information, we'll probably use delegation.

理解:当我们期望回调方法有返回值的时候,如UITableView的dataSource场景,我们使用的是delegate。这里不用block的原因是block里面的内容是一个镜像出来的,不是数据当前最真实的状态。

4.delegate callbacks are more process oriented(or multi-step process) and blocks are more results oriented.

delegate的回调是以过程为导向,block更多的是结果导向。

理解:如UIWebview在加载的过程中,当链接将要被打开时,页面加载结果,加载失败等过程都是以delegate来实现回调的,而系统的“presentViewController: animated: completion:”方法的completion是指当弹出页面结束时的一个回调。实际这个界线不是很明显。

5.block会快于delegate(maybe?)。

理解:AVPlayer的播放时间回调中,这更多像一个过程,而不是一个结果。因些参考第4点的话,我们更应该使用delegate。但是实际上这个回调使用的是block,推测可能是为了提高方法调用的速度,block可以直接被调用,不然每秒几百次回调,用delegate的话方法查找(runtime实现)可能会降低响应速度。