通常我们在调用代理方法前,都会对委托对象是否能响应代理方法进行判断,出现以下代码段:
if(_delegate && [_delegate respondsToSelector:@selector(MethodsName)]) {
[_delegate MethodsName ];
}
使用这段代码我们可以很容易判断出委托对象是否实现了指定的代理方法,但是如果需要频繁的调用代理方法,其实除了第一次检测的必须的,后续的检测是多余的,不大可能出现之前可以响应,后面突然无法响应的情况。鉴于此特殊情况,其实我们可以在第一次检测后,将检测结果缓存下来,作为下次使用代理方法时的参考标准。
重点来了!!!!!!!
通常情况下,我们经常用布尔值来做标识符,但是如果我们的代理方法很多,就会建立很多布尔类型的标识符来表示每一个代理方法的是否可执行。如果单纯的实现功能,这是完全没有问题的,但是代码也会多几分丑陋。如何避免这种情况呢? 我们可以使用“位字段”来解决这一丑陋现象,而且位字段可以节省内存空间,使代码更加优雅。
位字段
位字段是一个signed int 或 unsigned int 类型变量中的一组相邻的位(C99和C11新增了_Bool类型的位字段)。位字段通过一个结构声明来建立,该结构声明为每个字段提供标签,并确定该字段的宽度。eg:
struct {
unsigned int a: 1;
_Bool c: 1;
signed int b: 32;
}BitField;
以上就是一个位字段结构体的定义。在这里我们需要注意的就是,声明的顺序,BitField经计算是占8个字节,但是如果我们将_Bool c: 1 和 signed int b: 32;调换位置,会发现BitField所占字节变为了12。
关于位字段的就简单的介绍到这,具体可以参考此链接:浅谈C语言中的位段。
回归正题,针对委托模式要进行的修改就是重写属性中关于delegate的setter方法:
- (void)setDelegate:(id)delegate { _delegate = delegate; DelegateStatus.respondsToSelector = [delegate respondsToSelector:@selector(optimizingDelegateMethodsByBitfield)]; }
我们在设置委托对象时,预先检测委托对象是否可以响应代理方法,并将结果缓存到位字段中。当我们在使用的时候可以直接根据位字段缓存的结果来判断是否执行代理方法。
if (DelegateStatus.respondsToSelector) {
printf("%zd\n",sizeof(DelegateStatus));
[self.delegate optimizingDelegateMethodsByBitfield];
}
好了,到此关于适用位字段优化委托模式就介绍到这,还是很简单的,感觉主要是对位字段概念的理解掌握(后悔大学没好好学C语言 (≧﹏ ≦))(≧﹏ ≦),如果我对位字段的简单介绍有误,欢迎指正。
虽然很简单,但还是提供一下Demo地址吧:github地址连接
网友评论