iOS Delegate模式性能優(yōu)化的小方法

在我們日常開發(fā)當中,對于delegate的使用都不會陌生。
一般我們使用delegate的方式大概就是像下面這樣:

@protocol GRHNetworkFetcherDelegate <NSObject>

@optional
- (void)didReceiveData:(NSData *)data;
- (void)didFailWithError:(NSError *)error;
- (void)didUpdateProgressTo:(CGFloat)progress;

@end

@interface GRHNetworkFetcher : NSObject

@property (nonatomic, assign)id<GRHNetworkFetcherDelegate> delegate;

@end 

然后在.m文件中判斷:
- (void)doSometing {
if ([self.delegate respondsToSelector:@selector(didReceiveData:)]) {
[self.delegate didReceiveData:nil];
}
}

這段代碼用 respondsToSelector: 來判斷委托對象是否實現(xiàn)了相關方法。如果實現(xiàn)了,就調用;如果沒有實現(xiàn),就不執(zhí)行任何操作。這樣的話,delegate 對象就可以完全按照其需要來實現(xiàn)委托協(xié)議中的方法了,不用擔心因為哪個方法沒實現(xiàn)而導致程序出bug。即便沒有設置委托對象,程序也能照常運行,因為給nil發(fā)送消息將使if語句的值成為false。
可是如果拼房的執(zhí)行此操作的話,除了第一次的檢測結果有用之外,后續(xù)的檢測可能都是多余的。如果委托對象本身沒變,那么不太可能突然響應某個原來不能響應的selector,也不太會突然無法響應某個原來可以響應的 selector。鑒于此,我們通常把委托對象能否響應某個協(xié)議方法這一信息緩存起來,以優(yōu)化程序效率。(然而印象中Runtime的信號量自己是有緩存機制的,所以外部多次調用 respondsToSelector: 方法,底層應該有緩存起來的。
我們可以用位段數(shù)據(jù)類型來緩存這個檢測結果,把結構體中某個字段所占用的二進制個數(shù)設為特定的值。比如這樣:

struct {
    unsigned int fieldA : 8;
    unsigned int fieldB : 4;
    unsigned int fieldC : 2;
    unsigned int fieldD : 1;
};

在結構體中,fieldA位段將占用8個二進制位,fieldB占用4個,fieldC占用2個,fieldD占用1個。于是,fielA可以表示0-255之前的值,而fieldD則可以表示0或1這兩個值。我們可以像fieldD這樣,把委托對象是否實現(xiàn)了協(xié)議中的相關方法這一信息緩存起來。如果創(chuàng)建的結構體中只有大小為1的位段,那么就能把許多 Boolean 值塞入一小塊數(shù)據(jù)里面了。
改寫如下:

@interface GRHNetworkFetcher() {
    struct {
        unsigned int didReceiveData          : 1;
        unsigned int didFailWithError        : 1;
        unsigned int didUpdateProgressTo     : 1;
    } _delegateFlags;
}

@end

實現(xiàn)緩存的代碼可以寫在 delegateset 方法里:

- (void)setDelegate:(id<GRHNetworkFetcherDelegate>)delegate {
    _delegate = delegate;
    _delegateFlags.didReceiveData = [delegate respondsToSelector:@selector(didReceiveData:)];
    _delegateFlags.didFailWithError = [delegate respondsToSelector:@selector(didFailWithError:)];
    _delegateFlags.didUpdateProgressTo = [delegate respondsToSelector:@selector(didUpdateProgressTo:)];
}

這樣在每次調用 delegate 相關方法前,就不用檢測委托對象是否能響應給定的 selector,而是直接查詢結構體里的標志:

- (void)doSometing {
    if (_delegateFlags.didReceiveData) {
        [self.delegate didReceiveData:nil];
    }
}

在相關方法要調用很多次時,值得進行這種優(yōu)化。而是否需要優(yōu)化,則應依照具體代碼來定。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容