前言
相信做過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];
}
在相關方法要調用多次時,值得進行這種優化,而是否需要優化,則應依照具體代碼來定。這就需要分析代碼性能,并找出瓶頸,若發現執行速度需要改進,則可使用該技巧。如果要頻繁通過數據源協議從數據源中獲取多份相互獨立的數據,那么這項優化技術極有可能會提高程序效率