這篇文章你將看到以下內(nèi)容:
- Efficetive Objective-C 2.0閱讀筆記一些有價值的建議
1.對象內(nèi)部盡量直接訪問實例變量
直接訪問實例變量為直接訪問內(nèi)存,效率比調(diào)用屬性高。
- 訪問實例變量不會觸發(fā)KVO
-
-init
及-dealloc
方法中應(yīng)使用實例變量 - 對象內(nèi)部應(yīng)盡量遵守如下原則:取值采用實例變量求类,賦值采用屬性撞叽。
2.消息轉(zhuǎn)發(fā)機(jī)制流程
3.盡量使用不可變對象
- 集合中盡量添加不可變對象,否則可能會發(fā)生與集合本身語義有分歧的后果,eg:
NSMutableArray * arr1 = @[@1].mutableCopy;
NSMutableArray * arr2 = @[@1,@2].mutableCopy;
NSSet * set = [NSSet setWithObjects:arr1,arr2, nil];
[arr1 addObject:@2];//至此set中居然包含了兩個相同的元素
NSSet * setCopy = [set copy];//書中此處表述setCopy應(yīng)只有一個元素停蕉,然實測有兩個相同元素
- 對象對外公開集合類盡量使用不可變集合
- 對象對外公開
readOnly
屬性勺三,內(nèi)部可以通過重新聲明為readWrite
來使用屬性值雷滚。如此操作后和能會由于競態(tài)使得部分情況外部可以修改屬性值,外部也可通過KVC來更改屬性值
4.將類的實現(xiàn)代碼分散到便于管理的數(shù)個分類之中
通過分類機(jī)制吗坚,可以把類代碼分成很多個易于管理的小塊祈远,以便單獨檢視。
之所以要將類代碼打散到分類中還有個原因商源,就是便于調(diào)試:對于某個分類中的所有方法來說车份,分類名稱都會出現(xiàn)在其符號中。
將應(yīng)該視為“私有”的方法歸入名叫Private的分類中牡彻,以隱藏實現(xiàn)細(xì)節(jié)扫沼。
5.在-dealloc中只釋放引用并解除監(jiān)聽
- 在
-dealloc
方法里,應(yīng)該做的事情就是釋放指向其他對象的引用,并取消原來訂閱的“鍵值觀測”(KVO)或NSNotificationCenter等通知缎除,不要做其他事情严就。 - 如果對象持有文件描述符等系統(tǒng)資源,那么應(yīng)該專門編寫一個方法來釋放此種資源器罐。這樣的類要和其他使用者約定:用完資源后必須調(diào)用close方法梢为。
- 執(zhí)行異步任務(wù)的方法不應(yīng)再
-dealloc
里調(diào)用;只能子啊正常狀態(tài)下執(zhí)行的那些方法也不應(yīng)在-dealloc
里調(diào)用技矮,因為此時對象已處于正在回收的狀態(tài)了抖誉。
6.以自動釋放池降低內(nèi)存峰值
比方說,在循環(huán)中不斷地創(chuàng)建的臨時對象衰倦。即便這些對象在調(diào)用完方法之后就就不在使用了袒炉,他們也依然處于存活狀態(tài),因為目前還在自動釋放池里樊零,等待系統(tǒng)稍后將其釋放并回收我磁。然而,自動釋放池要等線程執(zhí)行下一次runLoop時才會清空驻襟。這樣依賴夺艰,執(zhí)行for循環(huán)時,應(yīng)用程序所占內(nèi)存量就會持續(xù)上漲沉衣,而等到所有臨時對象都釋放后郁副,內(nèi)存用量又會突然下降。
然而在循環(huán)中合理的位置添加自動釋放池豌习,應(yīng)用程序在執(zhí)行循環(huán)時的內(nèi)存峰值就會降低存谎。
7.多用派發(fā)隊列,少用同步鎖
濫用@synchronized(self)
會降低代碼效率肥隆,因為共用同一個鎖的那些同步塊既荚,都必須按順序執(zhí)行。若想實現(xiàn)同步機(jī)制栋艳,可以以并行隊列恰聘、同步任務(wù)及柵欄實現(xiàn),代碼如下:
_syncQueue = dispatch_queue_create("com.syncQ.Wicky", DISPATCH_QUEUE_CONCURRENT);///創(chuàng)建并行隊列
///getter
-(NSString *)someString {
__block NSString * localString;
dispatch_sync(_syncQueue, ^{
localString = _someString;
});
return localString;
}
///setter
-(void)setSomeString:(NSString *)someString {
dispatch_barrier_async(_syncQueue, ^{
_someString = someString;
});
}
8.多用GCD吸占,少用performSelector系列方法
由于在編譯器無法確定performSelector方法是否具有返回值晴叨,故編譯器沒有對對象進(jìn)行引用計數(shù)管理,因此可能造成內(nèi)存泄漏矾屯。
另外performSelector返回值只能是id類型的對象篙螟,基本數(shù)據(jù)類型可能需要開發(fā)人員進(jìn)行進(jìn)一步的類型轉(zhuǎn)換。
如果想要添加延時任務(wù)问拘,條件允許的情況下應(yīng)盡可能選擇GCD遍略。
9.合理使用GCD與NSOperation
GCD為純C的API惧所,而NSOperation則是OC對象。與NSOperation比起來GCD更加輕量绪杏,然而NSOperation卻有以下幾點在使用上更加便捷:
- 取消操作
- 指定依賴關(guān)系
- 提供KVO監(jiān)聽
- 指定優(yōu)先級
- 重用對象
10.多用Block枚舉下愈,少用for循環(huán)
Block枚舉擁有其他遍歷方式具備的所有優(yōu)勢,而且還能帶來更多好處蕾久。與快速遍歷法相比势似,他還要多用一些代碼,可是卻能提供遍歷時所針對的下標(biāo)僧著,在遍歷字典時也能同時提供鍵與值履因,而且還有選項可以開啟并發(fā)迭代功能,所以多寫這點代碼還是值得的盹愚。
11.精簡+initialize與+load的實現(xiàn)代碼
- 在加載階段栅迄,如果類實現(xiàn)了
+load
方法,那么系統(tǒng)就會先調(diào)用他皆怕。分類里也可以定義此方法毅舆,類的+load
方法要比分類中的先調(diào)用。與其他方法不同愈腾,+load
方法不參與覆寫機(jī)制憋活。 - 首次使用某個類之前,系統(tǒng)會向其發(fā)送
+initialize
消息虱黄。由于此方法遵從普通的覆寫機(jī)制悦即,所以通常應(yīng)該在里面判斷當(dāng)前要初始化的是哪個類。 -
+load
與+initialize
方法都應(yīng)該實現(xiàn)的精簡一些橱乱,這有助于保持應(yīng)用程序的響應(yīng)能力盐欺,也能減少引入“依賴環(huán)”的幾率。 - 無法在編譯器設(shè)定的全局常量仅醇,可以放在
+initialize
方法里初始化。