23、通過委托與數據源協議進行對象間通信
如果要在委托對象上調用可選方法,那么必須提前使用類型信息查詢方法判斷這個委托對象能否響應相關選擇子。
if ( [_delegate respondsToSelector:@selector(networkFetcher:didReceiveData:)]){
[_delegate networkFetcher:self didReceiveData:data];
}
這段代碼用“respondsToSelector:”來判斷委托對象是否實現相關方法。如果實現了就調用,如果沒實現,就不執行任何操作。
delegate 對象中的方法名也一定要起得很恰當才行。方法名應該準確描述當前發生的事件以及 delegate 對象為何要獲知此事件。
如果委托方法多次調用,每次都檢測委托對象是否能相應此選擇子,那就顯得多余了。可以在實例中嵌入一個含有位段的結構體作為其實例變量,而結構體中的每個位段則表示 delegate 對象是否實現了協議中的相關方法。
@interface EOCNetworkFetcher () {
struct {
unsigned int didReceiveData : 1;
unsigned int didFailWithError : 1;
unsigned int didUpdateProgressTo : 1;
} _delegateFlags;
}
這個結構體用來緩存委托對象是否能相應特定的選中子。實現緩存功能所用的代碼可以寫在 delegate 屬性所對應的設置方法里:
-(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 的相關方法前,就不用檢測委托對象是否能相應給定的選擇子了,而是直接查詢結構體里的標準:
if ( _delegateFlags.didUpdateProgressTo ){
[_delegate networkFetcher:self didUpdateProgressTo:currentProgress];
}
委托模式為對象提供了一套接口,使其可由此將相關事件告知其他對象。
將委托多選應該支持的接口定義成協議,在協議中把可能需要處理的事件定義成方法。
當某對象需要從另外一個對象中獲取數據時,可以使用委托模式。這種情況下,該模式稱為“數據源協議”。
若有必要,可實現含有位段的結構體,將委托對象是否能響應相關協議方法這一信息緩存至其中。
24、將類的實現代碼分散到便于管理的數個分類之中
類中經常容易填滿各種方法,而這些方法的代碼則全部堆在一個巨大的實現文件里。有時這么做是合理的,因為即便通過重構把這個類打散,效果也不會更好。在此情況下,可以通過 Objective-C 的“分類”機制,把類代碼按邏輯劃分入幾個分區中,這對開發與調試都有好處。
使用分類機制把類的實現代碼劃分成易于管理的小塊。
將應該視為“私有”的方法歸入名叫 Private 的分類中,以隱藏實現細節。
25、總是為第三方類的分類名加前綴
向第三方類中添加分類時,總應該給其名稱加上你專用的前綴。
向第三方類添加分類時,總應給其中的方法名加上你專用的前綴。
26、勿在分類中聲明屬性
屬性是分裝數據的方式。盡管從技術上說,分類里也可以聲明屬性,但這種做法還是要盡量避免。原因在于,除了“class-continuation 分類”之外,其他分類都無法向類中新增實例變量,因此,他們無法把實現屬性所需要的實例變量合成出來。
把封裝數據所用的全部屬性都定義在主接口里。
在“class-continuation 分類”之外的其他分類中,可以定義存取方法,但盡量不要定義屬性。
27、使用“class-continuation 分類”隱藏實現細節
通過“class-continuation 分類”向類中新增實例變量。
如果某屬性在主接口中聲明為“只讀”,而類的內部又要用設置方法修改此屬性,那么久在“class-continuation 分類”中將其擴展為“可讀寫”。
把私有方法的原型聲明在“class-continuation 分類”里面。
若想使類所遵循的協議不為人所知,則可于“class-continuation 分類”中聲明。
28、通過協議提供匿名對象
協議可在某種程度上提供匿名類型。具體的對象類型可以淡化成遵從某協議的 id 類型,協議里規定了對象所應實現的方法。
使用匿名對象來隱藏類型名稱(或類名);
如果具體類型不重要,中要的是對象能夠相應(定義在協議里的)特定方法,那么可使用匿名對象來表示。