在設計接口的時候,委托是常用的交互方式,一般的,我們在使用協議時會寫出以下代碼。
if ([delegate respondsToSelector:@selector(someMothod:)]) {
[delegate someMothod:(id)sender];
}
一般情況下沒有問題,事實上,以上代碼可以滿足大部分的需求,但是假設你所實現的協議方法是一個類似網絡下載進度回調的功能,每隔很短的小段時間就需要回調一次呢?
你會發現,除了第一次檢測委托對象是否響應某個選擇子有意義外,之后的檢測都是多余的。如果委托對象本身沒變,那么不大可能會忽然不能響應某個選擇子。鑒于此,我們可以把委托對象能否響應某個協議方法這一信息緩存起來,已優化程序效率。
假設現在有一個進度回調的協議方法
- (void)networkDidUpdateProgressTo:(float)progerss;
以上方法由于需要監聽進度,需要頻繁地回調progress參數,如果能夠緩存委托對象能否響應的信息,我們就不必每次都去執行以下函數
if ([delegate respondsToSelector:@selector(someMothod:)])
將方法相應能力緩存起來的最佳途徑就是使用C語言的“位段”數據類型。
這里簡單介紹一下位段:
什么是位段呢? 位段是 C 語言特有的數據結構, 它允許我們定義一個由位組成的段, 并可為它賦以一個名字。
二進制位是數據的基本單位,它比字節還小,一個字節由 8 位組成, 而在某些計算機系統中則可能是 16 位。
事實上,如果需要標志一個信息,一位就足夠了,但是由于字節是存儲的最小單位,所以所有的變量至少要使用一個字節(比如BOOL值)。
如果我們想在一個很大的表中存儲很多標志, 那么 "被浪費" 的內存空間是很可觀的。幸運的是,在 C 語言中, 我們可以使用叫做位段的構造類型來定義一個結構體,從而定義某個字段所用的二進制位個數為某個特定的值。
struct data{ //包含位段的結構體
unsigned int fieldA : 8; //位段fieldA,占8二進制位
unsigned int fieldB : 4; //位段fieldB,占4二進制位
unsigned int fieldC : 2; //位段fieldC,占2二進制位
unsigned int fieldD : 1; //位段fieldD,占1二進制位
}
//位段列表的形式為: 類型說明符 位域名:位域長度
以上結構體中,fieldA 位段將占用 8 個二進制位,fieldB 則為 4個,以此類推。于是,fieldA 可以表示 0 至 255 之間的值,而fieldD可以表示 0 或 1 這兩個值。
我們可以像 fieldD 這樣,把委托對象是否實現了協議中的相關方法這一信息緩存起來。如果創建的結構體中只有大小為 1 的位段,那么就能把很多 Boolean 值塞入一小塊數據里面了(原來存一個BOOL值的空間,現在能存8個),我們現在文件中聲明一個結構體。
struct {
unsigned int delegateMothod1 : 1;
unsigned int delegateMothod2 : 1;
unsigned int delegateMothod3 : 1;
} _delegateFlags;
然后重寫我們的delegate的setter方法:
-(void)setDelegate:(id<personalDelegate>)delegate
{
_delegate=delegate;
_delegateFlags.delegateMothod1=[delegate respondsToSelector:@selector(delegateMothod1:)];
_delegateFlags.delegateMothod2=[delegate respondsToSelector:@selector(delegateMothod2:)];
_delegateFlags.delegateMothod3=[delegate respondsToSelector:@selector(delegateMothod3:)];
}
現在委托對象如果能夠相應協議方法,位段就可以將其以一位的大小緩存起來,然后我們在之后調用委托對象的相關方法時,就不用檢測委托對象是否能響應給定的選擇子了,而是直接查詢結構體里的標志:
if (_delegateFlags._delegateFlags.delegateMothod1){
[_delegate delegateMothod1:];
}
在相關方法要調用很多次的時候,值得進行這種優化,而是否需要優化,則應依照具體代碼來定。這需要分析代碼性能,并找出瓶頸,若發現執行速度需要改進,則可使用此技巧。如果要頻繁通過數據源協議從數據源中獲取多分相互獨立的數據,那么這項優化技術極有可能會提高程序效率。