前言
相信做过iOS开发的人都使用过delegate(并不是设置模式中的proxy
),这里就以一个实例,来分享一下开发中大量使用某个delegate方法的优化方案
位段
位段,C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域”( bit field) 。利用位段能够用较少的位数存储数据。
struct data {
unsigned int fieldA : 8;
unsigned int fieldB : 4;
unsigned int fieldC : 2;
unsigned int fieldD : 1;
}
在结构体中,fieldA位段将占用8个二进制位,fieldB占用4个,fieldC占用2个,fieldD占用1个。于是,fieldA可以表示0至255之间的值,而fieldD可以表示0或1这两个值,我们可以像fieldD这样,把委托对象是否实现了协议中的相关方法这一信息缓存起来。如果创建结构体中只有大小为1的位段,那么就能把许多Boolean值塞入一小块数据里面了。以网络数据获取器为例,可以在该实例中嵌入一个含有位段的结构体作为其实例变量,而结构体中的每个位段则表示delegate
对象是否实现了协议中的相关方法
delegate缓存
@interface NetworkFetcher () {
struct {
unsigned int didReceiveData : 1;
unsigned int didFailWithError : 1;
unsigned int didUpdateProgressTo : 1;
}_delegateFlags;
}
@end
上面的实例变量是个结构体,其中含有三个位段,每个位段都与delegate所遵从的协议中某个可选(@optional
)方法相对应。这个结构体用来缓存委托对象是否能响应特定的选择子,实现缓存功能所用的代码可以写在delegate属性所对应的设置方法里
- (void)setDelegate:(id<NetworkFetcherDelegate>)delegate {
_delegate = delegate;
_delegate.didReceiveData = [delegate respondsToSelector:@selector(NetworkFetcher:didReceiveData)];
_delegate.didFailWithError = [delegate respondsToSelector:@selector(NetworkFetcher:didFailWithError)];
_delegate.didUpdateProgressTo = [delegate respondsToSelector:@selector(NetworkFetcher:didUpdateProgressTo)];
}
这样的话,每次调用delegate的相关方法之前,就不用检测委托对象是否能响应给定的选择子了,而是直接查询结构体里的标识
if (_delegate.didUpdateProgressTo) {
[_delegate NetworkFetcher:self didUpdateProgressTo:currentProgess];
}
在相关方法要调用多次时,值得进行这种优化,而是否需要优化,则应依照具体代码来定。这就需要分析代码性能,并找出瓶颈,若发现执行速度需要改进,则可使用该技巧。如果要频繁通过数据源协议从数据源中获取多份相互独立的数据,那么这项优化技术极有可能会提高程序效率