通常我們在調(diào)用代理方法前,都會對委托對象是否能響應(yīng)代理方法進(jìn)行判斷漾稀,出現(xiàn)以下代碼段:
if(_delegate && [_delegate respondsToSelector:@selector(MethodsName)]) { ? ? ? ? ? ? ? ??
? ? [_delegate MethodsName ];
}
使用這段代碼我們可以很容易判斷出委托對象是否實現(xiàn)了指定的代理方法聪姿,但是如果需要頻繁的調(diào)用代理方法育瓜,其實除了第一次檢測的必須的似袁,后續(xù)的檢測是多余的存璃,不大可能出現(xiàn)之前可以響應(yīng)淋叶,后面突然無法響應(yīng)的情況阎曹。鑒于此特殊情況,其實我們可以在第一次檢測后煞檩,將檢測結(jié)果緩存下來处嫌,作為下次使用代理方法時的參考標(biāo)準(zhǔn)。
重點來了U迮取Q!!DW怠!墓猎!
通常情況下捆昏,我們經(jīng)常用布爾值來做標(biāo)識符,但是如果我們的代理方法很多毙沾,就會建立很多布爾類型的標(biāo)識符來表示每一個代理方法的是否可執(zhí)行骗卜。如果單純的實現(xiàn)功能,這是完全沒有問題的,但是代碼也會多幾分丑陋寇仓。如何避免這種情況呢举户? 我們可以使用“位字段”來解決這一丑陋現(xiàn)象,而且位字段可以節(jié)省內(nèi)存空間遍烦,使代碼更加優(yōu)雅俭嘁。
位字段
位字段是一個signed int 或 unsigned int 類型變量中的一組相鄰的位(C99和C11新增了_Bool類型的位字段)。位字段通過一個結(jié)構(gòu)聲明來建立乳愉,該結(jié)構(gòu)聲明為每個字段提供標(biāo)簽兄淫,并確定該字段的寬度。eg:
struct {
? ? unsigned int a: 1;
? ? _Bool c: 1;
? ? signed int b: 32;?
}BitField;
以上就是一個位字段結(jié)構(gòu)體的定義蔓姚。在這里我們需要注意的就是捕虽,聲明的順序,BitField經(jīng)計算是占8個字節(jié)坡脐,但是如果我們將_Bool c: 1 和 signed int b: 32;調(diào)換位置泄私,會發(fā)現(xiàn)BitField所占字節(jié)變?yōu)榱?2。
關(guān)于位字段的就簡單的介紹到這备闲,具體可以參考此鏈接:淺談C語言中的位段晌端。
回歸正題,針對委托模式要進(jìn)行的修改就是重寫屬性中關(guān)于delegate的setter方法:
- (void)setDelegate:(id)delegate { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?_delegate = delegate; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DelegateStatus.respondsToSelector = [delegate ? ? ? ?respondsToSelector:@selector(optimizingDelegateMethodsByBitfield)]; ? ? ? ? ? ? ? ? ? ? ?}
我們在設(shè)置委托對象時恬砂,預(yù)先檢測委托對象是否可以響應(yīng)代理方法咧纠,并將結(jié)果緩存到位字段中。當(dāng)我們在使用的時候可以直接根據(jù)位字段緩存的結(jié)果來判斷是否執(zhí)行代理方法泻骤。
if (DelegateStatus.respondsToSelector) { ? ? ? ? ?
printf("%zd\n",sizeof(DelegateStatus));
[self.delegate optimizingDelegateMethodsByBitfield];
}
好了漆羔,到此關(guān)于適用位字段優(yōu)化委托模式就介紹到這,還是很簡單的狱掂,感覺主要是對位字段概念的理解掌握(后悔大學(xué)沒好好學(xué)C語言 (≧﹏ ≦))(≧﹏ ≦),如果我對位字段的簡單介紹有誤演痒,歡迎指正。
雖然很簡單趋惨,但還是提供一下Demo地址吧:github地址連接