1. 程式人生 > >OC中如何優化代理是否響應某個方法

OC中如何優化代理是否響應某個方法

base sign some nds lda toc something lec replace

看以下示例代碼:

if([_delegate respondsToSelector:  
    @selector(someClassDidSomething:)){  
    [_delegate someClassDidSomething];  
}  

一般情況下,我們在寫代理的時候都是這樣判斷某個對象有沒有實現代理中的某個方法。這樣固然可以,但是如果某個代理方法調用的頻率非常非常高,因為在調用這個代理方法的時候,都需要做一次if判斷,if判斷的時候又要執行respondsToSelector:方法,所以效率會顯得很低下。此時,我們可以采用緩存的辦法,來進行優化。

在C語言中有一種乏人問津的特性——可以把結構體中得某個字段在內存中所占用的位數設置為特定的值。

比如:

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

在這個結構體中,fieldA占8位,所以可以表示的範圍是0~255,fieldD只占一位,則可以表示的數是0和1。0和1能表示什麽,很明顯,可以用來表示布爾(BOOL)類型的值。

現在看優化的代碼如下:

@protocol EOCNetworkFetcherDelegate  
  
@optional  
-(void)networkFetcher:(EOCNetworkFetcher *)fetcher didReceiveData:(NSData *)data;  
-(void)networkFetcher:(EOCNetworkFetcher *)fetcher didFailError:(NSError *)error;  
-(void)networkFetcher:(EOCNetworkFetcher *)fetcher didUpdateProgressTo:(float)progress;  
  
@end  

優化代碼:

@interface EOCNetworkFetcher(){  
    struct{  
        unsigned int didReceiveData : 1;  
        unsigned int didReceiveData : 1;  
        unsigned int didReceiveData : 1;  
    } _delegateFlags;  
}  
@end  

在setDelegate中,可以寫以下代碼,來優化:

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

在設置完delegate以後,就可以采用_delegateFlags中的具體標誌而不需要每次都調用respondsToSelector:來判斷是否響應了某個方法。

if(_delegateFlags.didUpdateProgressTo){  
    [_delegate networkFetcher:self didUpdateProgressTo:currentProgress];  
}  

OC中如何優化代理是否響應某個方法