通常我們在調用代理方法前,都會對委托對象是否能響應代理方法進行判斷,出現以下代碼段:
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地址連接