文章目录
  1. 1. 委托模式
  2. 2. 优化

委托模式


对象之间经常相互通信,而通信方式有很多。Object-C开发者广泛使用的一种名叫“委托模式”的编程设计模式来实现对象间的的通信,该模式的主旨是:定义一套接口,某对象若想接受另一个对象的委托,则需遵从此接口,以便成为其“委托对象”。而这“另一个对象”则可以给其委托对象回传一些信息,也可以发生相关事件时通知委托对象。

通常delegate对象中的方法名也一定要起得恰当才行。方法名应该准确描述当前发生的事件以及delegate对象为何要获知此事件。在调用delegate对象中的方法时,总是应该把发起委托的实例也一并传入方法中,这样,delegate对象在实现相关方法时,就能根据传入的实例分别执行不同的代码了。若没有此信息,则委托对象在同一时间只能执行一套逻辑,这么做不太好。

优化


在实现委托模式时,如果协议中的方法是可选得,那么就会写出一大批类似下面的代码来:

1
2
3
4
if ([_delegate respondsToSelector:@selector(someClassDidSomething:)])
{
[_delegate someClassDidSomething];
}

很容易用代码查出某个委托对象是否能响应特定的选择子,可是如果频繁执行此操作的话,那么除了第一次检测的结果有用之外,后续的检测可能都是多余的。如果委托对象本身没变,那么不太可能会突然响应某个原来不能响应的选择子,也不太会突然无法响应某个原来可以响应的选择子。鉴于此,我们可以把委托对象能否响应某个协议方法这一信息缓存起来,以优化程序效率。

将方法响应能力缓存起来的最佳途径是使用“位段”数据类型,我们可以把结构体中的字段占用的二进制位个数设为一个字节,从而用0和1表示方法是否被响应。

下面举个例子:

在“class-continuation分类”中新增实例变量,这个新增的实例变量是个结构体,用来缓存方法的响应与否。

1
2
3
4
struct{
unsigned int didReceiveData : 1;
unsigned int didFailWithError : 1;
} _delegateFlags;

这个结构体用来缓存委托对象是否能响应特定的选择子。实现缓存功能所用的代码可以写在delegate属性所对应的设置方法里:

1
2
3
4
5
6
7
-(void)setDelegate:(id<GXZNetWorkFetcher>)delegate {
_delegate = delegate;
_delegateFlags.didReceiveData =
[delegate respondsToSelector:@selector(networkFetcher:didReceiveData:)];
_delegateFlags.didFailWithError =
[delegate respondsToSelector:@selector(networkFetcher:didFailWithError:)];
}

这样的话,每次调用delegate的相关方法之前,就不用检测委托对象是否能响应给定的选择子了,而是直接查询结构体里的标志:

1
2
3
-(_delegateFlags.didReceiveData) {
[_dlegate networkFetcher:self didReceiveData:data];
}

在相关方法要调用很多次时,值得进行这种优化。而是否需要优化,则应依照具体代码来定。这就需要分析代码性能,并找出瓶颈,若发现执行速度需要改进,则可使用此技巧。如果频繁的通过数据源协议从数据源中获取多份相互独立的数据,那么这项优化技术极有可能就会提高程序效率。

文章目录
  1. 1. 委托模式
  2. 2. 优化