本篇是我閱讀《Effective Objective-C 2.0》的摘要與總結(jié)允蜈,如有疑問磷箕,铅搓,我會附上例子解釋。
一搀捷、熟悉Objective-C
- 了解Objective-C語言的起源
- Objective-C為C語言添加了面向?qū)ο筇匦裕瞧涑嗤bjective-C使用動態(tài)綁定的消息結(jié)構(gòu)嫩舟,也就是說,在運行時才會檢查對象類型怀偷。接收一條消息之后家厌,究竟應執(zhí)行何種代碼,由運行環(huán)境而非編譯器來決定椎工。
- 理解C語言的核心概念有助于寫好Objective-C程序饭于。尤其要掌握內(nèi)存模型與指針蜀踏。
- 在類的頭文件中盡量少引入其他頭文件
- 除非確有必要,否則不要引入頭文件掰吕。一般來說果覆,應在某個類的頭文件中使用向前聲明(forward declaring)來提及別的類,并在實現(xiàn)文件中引入那些類的頭文件殖熟。這樣做可以盡量降低類之間的耦合局待。
- 有時無法使用向前聲明,比如要聲明某個類遵循一項協(xié)議菱属。這種情況下钳榨,盡量把“該類遵循某協(xié)議”的這條聲明移至“class-continuation”分類中。如果不行的話纽门,就把協(xié)議單獨放在一個頭文件中薛耻,然后將其引入。
- 多用literal語法赏陵,少用與之等價的方法
比如多用NSArray *array = @[@1,@2];
少用NSArray *array = [NSArray arrayWithObjects:@1,@2,nil];
- 應該使用literal語法來創(chuàng)建字符串饼齿,數(shù)值,數(shù)組瘟滨,字典候醒。與創(chuàng)建此類對象的常規(guī)方法相比,這么做更加簡明扼要杂瘸。
- 應該通過取下標操作來訪問數(shù)組下標或字典中的鍵所對應的元素倒淫。
- 用literal語法創(chuàng)建數(shù)組或字典時,若值中有nil败玉,則會拋出異常敌土。因此,務必確保值里不含nil运翼。
- 多用類型常量返干,少用#define預處理指令
- 不要用預處理指令定義常量。這樣定義出來的常量不含類型信息血淌,編譯器只是會在編譯前據(jù)此執(zhí)行查找與替換操作矩欠。即使有人重新定義了常量值,編譯器也不會產(chǎn)生警告信息悠夯,這將導致應用程序中的常量值不一致癌淮。
- 在實現(xiàn)文件中使用static const來定義只在編譯單元內(nèi)可見的常量。由于此類常量不在全局符號表中沦补,所以無需為其名稱加前綴乳蓄。
- 在頭文件中使用extern來聲明全局常量,并在相關(guān)實現(xiàn)文件中定義其值夕膀。這種常量要出現(xiàn)在全局符號表中虚倒,所以其名稱要加以區(qū)隔美侦,通常用與之相關(guān)的類名做前綴。
- 用枚舉表示狀態(tài)魂奥、選項菠剩、狀態(tài)碼
- 應該用枚舉來表示狀態(tài)機的狀態(tài)、傳遞給方法的選項遺跡狀態(tài)碼等值捧弃,給這些值起個易懂的名字赠叼。
- 如果把傳遞給某個方法的選項表示為枚舉型,而多個選項又可同時使用违霞,那么就將各選項值定義為2的冪嘴办,以便通過按位或者操作將其組合起來。
- 用NS_ENUM與NS_OPTIONS宏來定義枚舉類型买鸽,并指明其底層數(shù)據(jù)類型涧郊。這樣做可以確保枚舉是用開發(fā)者所選的底層數(shù)據(jù)類型實現(xiàn)出來的,而不會采用編譯器所選的類型眼五。
- 在處理枚舉類型的switch語句中不要實現(xiàn)default分支妆艘。這樣的話,加入新枚舉之后看幼,編譯器就會提示開發(fā)者:switch語句并未處理所有的枚舉批旺。
二、對象诵姜、消息汽煮、runtime
- 理解“屬性”這一概念
- 可以通過@property語法來定義對象中所封裝的數(shù)據(jù)。
- 通過“特質(zhì)”來指定存儲數(shù)據(jù)所需的正確語義
- 在設(shè)置屬性所對應的實例變量時棚唆,一定要遵從該屬性所聲明的語義暇赤。
- 開發(fā)iOS程序時,應該使用nonatomic屬性宵凌,因為atomic屬性會嚴重影響性能鞋囊。
- 在對象內(nèi)部盡量直接訪問實例變量
- 在對象內(nèi)部讀取數(shù)據(jù)時,應該直接通過實例變量來讀瞎惫,而寫入數(shù)據(jù)時溜腐,應該通過屬性來寫。
- 在初始化方法及dealloc方法中瓜喇,總是應該直接通過實例變量來讀寫數(shù)據(jù)挺益。
- 有時會使用惰性初始化技術(shù)配置某份數(shù)據(jù),這種情況下欠橘,需要通過屬性來讀取數(shù)據(jù)。
- 理解“對象等同性”這一概念
- 若想檢測對象的等同性现恼,請?zhí)峁癷sEqual:”與hash方法肃续。
- 相同的對象必須具有相同的hash碼黍檩,但是兩個hash碼相同的對象卻未必相同。
- 不要盲目的逐個監(jiān)測每條屬性始锚,而是應該依照具體需求來制定檢測方案刽酱。
- 編寫hash方法時,應該使用計算速度快而且哈希碼碰撞幾率低的算法瞧捌。
- 以“類族模式”隱藏實現(xiàn)細節(jié)
- 類族模式可以把實現(xiàn)細節(jié)隱藏在一套簡單的公共接口后面棵里。
- 系統(tǒng)框架中經(jīng)常使用類族。
- 從類族的公共抽象基類中繼承子類時要當心姐呐,若有開發(fā)文檔殿怜,則應首先閱讀。
- 在既有類中曙砂,使用關(guān)聯(lián)對象(Associated Object)存放自定義數(shù)據(jù)
- 可以通過“關(guān)聯(lián)對象”機制來把兩個對象連起來头谜。
- 定義關(guān)聯(lián)對象時可指定內(nèi)存管理語義,用以模仿定義屬性時所采用的“擁有關(guān)系”與“非擁有關(guān)系”鸠澈。
- 只有在其他做法不可行時才應選用關(guān)聯(lián)對象柱告,因為這種做法通常會引入難于查找的bug。
- 理解objc_msgSend的作用
- 消息由接受者笑陈,selector及參數(shù)構(gòu)成际度。給某對象“發(fā)送消息”也就相當于在該對象上調(diào)用方法。
- 發(fā)給某對象的全部消息都要由“動態(tài)消息派發(fā)系統(tǒng)”來處理涵妥,該系統(tǒng)會查出對應的方法乖菱,并執(zhí)行其代碼。
- 理解消息轉(zhuǎn)發(fā)機制
- 若對象無法響應某個selector妹笆,則進入消息轉(zhuǎn)發(fā)流程块请。
- 通過運行期的動態(tài)方法解析功能,我們可以在需要用到某個方法時再將其加入類中拳缠。
- 對象可以將其無法解讀的某些selector轉(zhuǎn)交給其他對象處理墩新。
- 經(jīng)過上述兩步后,如果還是沒辦法處理selector窟坐,那就啟動完整的消息轉(zhuǎn)發(fā)機制海渊。
- 用method swizzling調(diào)試黑盒方法
- 在runtime中,可以向類中新增或替換selector所對應的方法實現(xiàn)哲鸳。
- 使用另一份實現(xiàn)來替換原有的方法實現(xiàn)臣疑,這道工序叫做method swizzling,開發(fā)者常用此技術(shù)向原有視線中添加功能徙菠。
- 一般來說讯沈,只有調(diào)試程序的時候才需要在runtime中修改方法實現(xiàn),這種做法不宜濫用婿奔。
- 理解“類對象”的用意
- 每個實例都有一個指向Class對象的指針缺狠,用以表明其類型问慎,而這些Class對象則構(gòu)成了累的繼承體系。
- 如果對象類型無法在編譯期確定挤茄,那么就應該使用類型信息查詢方法來探知如叼。
- 盡量使用類型信息查詢方法來確定對象類型,而不要直接比較類對象穷劈,因為某些對象可能實現(xiàn)了消息轉(zhuǎn)發(fā)功能笼恰。
三、接口與API設(shè)計
- 用前綴避免命名空間沖突
- 選擇與你公司歇终、應用程序或者二者皆有關(guān)聯(lián)之名稱作為類名的前綴社证,并在所有代碼中均使用這一前綴。
- 若自己所開發(fā)的程序庫中用到了第三方庫练湿,則應為其中的名稱加上前綴猴仑。
- Apple宣稱保留使用所有兩字母前綴的權(quán)利,所以自己所選用的前綴最好是三字母的肥哎。
- 提供“全能初始化方法”
- 在類中提供一個全能初始化方法辽俗,并于文檔里指明。其它初始化方法均應調(diào)用此方法篡诽。
- 若全能初始化方法與超類不同崖飘,則需覆寫超類中對應方法。
- 如果超類的初始化方法并不適用于子類杈女,那么應該覆寫這個超類方法朱浴,并在其中拋出異常。
- 實現(xiàn)description方法
- 實現(xiàn)description方法返回一個有意義的字符串达椰,用以描述該實例翰蠢。
- 若想在調(diào)試時打印出更詳盡的對象描述信息,則應該實現(xiàn)debugDescription方法啰劲。
- 盡量使用不可變對象
- 盡量創(chuàng)建不可變的對象梁沧。
- 若某屬性僅可于對象內(nèi)部修改,則在“class-continuation分類”中將其由readonly屬性擴展為readwrite屬性蝇裤。
- 不要把可變的collection作為屬性公開廷支,而應提供相關(guān)方法,一次修改對象中的可變collection栓辜。
- 使用清晰而協(xié)調(diào)的命名方式
- 起名時應遵從標準的Objective-C命名規(guī)范恋拍,這樣創(chuàng)建出來的接口更容易為開發(fā)者所理解。
- 方法名要言簡意賅藕甩,從左至右讀起來要像個日常用語中的句子才好施敢。
- 方法名利不要使用縮略后的類型名稱。
- 給方法嗎起名時的第一要務就是確保其風格與你自己的代碼或所要集成的框架相符。
- 為私有方法名加前綴
- 給私有方法的名稱加上前綴僵娃,這樣可以很容易的將其通公共方法區(qū)分開羡藐。
- 不要單用一個下劃線做私有方法的前綴,因為這種做法的預留給蘋果公司用的悯许。
- 理解Objective-C錯誤模型
- 只有發(fā)生了可使整個應用程序崩潰的嚴重錯誤時,才使用異常辉阶。
- 在錯誤不那么嚴重的情況下先壕,可以指派委托方法來處理錯誤,也可把錯誤信息放在NSError對象里谆甜,經(jīng)由輸出參數(shù)返回給調(diào)用者垃僚。
- 理解NSCopying協(xié)議
- 若想令自己所寫的對象具有拷貝功能,則需實現(xiàn)NSCopying協(xié)議规辱。
- 如果自定義的對象分為可變版本與不可變版本谆棺,那么就要同時實現(xiàn)NSCopying與NSMutableCopying協(xié)議。
- 復制對象時需決定采用淺拷貝還是深拷貝罕袋,一般情況下應該盡量執(zhí)行淺拷貝改淑。
- 如果你所寫的對象需要深拷貝,那么可考慮新增一個專門執(zhí)行深拷貝的方法浴讯。
四朵夏、協(xié)議與分類
- 通過委托與數(shù)據(jù)源協(xié)議進行對象間通信
- 委托模式為對象提供了一套接口,使其可由此將相關(guān)事件告知其他對象榆纽。
- 將委托對象應該支持的接口定義成協(xié)議仰猖,在協(xié)議中把可能需要吃力的事件定義成方法。
- 當某對象需要從另外一個對象中獲取數(shù)據(jù)時奈籽,可使用委托模式饥侵。在這種情況下,該模式亦稱數(shù)據(jù)源協(xié)議衣屏。
- 若有必要躏升,可實現(xiàn)含有位段的結(jié)構(gòu)體,將委托對象是否能響應相關(guān)協(xié)議方法這一信息緩存至其中勾拉。
- 將類的實現(xiàn)代碼分散到便于管理的數(shù)個分類之中
- 使用分類機制把類的實現(xiàn)代碼劃分成易于管理的小塊煮甥。
- 將應該視為私有的方法歸入名叫Private的分類中,以隱藏實現(xiàn)細節(jié)藕赞。
- 總是為第三方類的分類名稱加前綴
- 向第三方類中添加分類時成肘,總應給其名稱加上你專用的前綴。
- 向第三方類中添加分類時斧蜕,總應給其中的方法名加上你專用的前綴双霍。
26.勿在分類中聲明屬性 - 把封裝數(shù)據(jù)所用的全部屬性都定義在主接口里。
- 在class-continuation分類之外的其他分類中,可以定義存取方法洒闸,但盡量不要定義屬性染坯。
- 使用class-continuation分類隱藏實現(xiàn)細節(jié)
- 通過class-continuation分類向類中新增實例變量。
- 如果某屬性在主接口中聲明為只讀丘逸,而類的內(nèi)部又要用設(shè)置方法修改此屬性单鹿,那么就在class-continuation分類中將其擴展為可讀寫。
- 把私有方法的原型聲明在class-continuation分類里面深纲。
- 若想使類遵循的協(xié)議不為人所知仲锄,則可于class-continuation分類中聲明。
- 通過協(xié)議提供匿名對象
- 協(xié)議可在某種程度上提供匿名類型湃鹊。具體的對象類型可以淡化成遵從某些一的id類型儒喊,協(xié)議里規(guī)定了對象所應實現(xiàn)的方法。
- 使用匿名對象來隱藏類型名稱或類名币呵。
- 如果具體類型不重要怀愧,重要的是對象能夠響應(定義在協(xié)議里的)特定方法,那么可使用匿名對象來表示余赢。
五芯义、內(nèi)存管理
- 理解引用計數(shù)
- 引用計數(shù)機制通過可以遞增遞減的計數(shù)器來管理內(nèi)存。對象創(chuàng)建好后妻柒,其保留計數(shù)至少為1.若保留計數(shù)為正毕贼,則對象繼續(xù)存活。當保留計數(shù)降為0時蛤奢,對象就被銷毀了鬼癣。
- 在對象生命期中,其余對象通過引用來保留或釋放此對象啤贩。保留與釋放操作分別會遞增及遞減保留計數(shù)待秃。
- 以ARC簡化引用計數(shù)
- 在ARC之后,程序員就無須擔心內(nèi)存管理問題了痹屹。使用ARC來編程章郁,可省去類中的許多樣板代碼。
- ARC管理對象生命期的辦法基本上就是:在合適的地方插入保留及釋放操作志衍。在ARC環(huán)境下暖庄,變量的內(nèi)存管理語義總是通過方法名來體現(xiàn)。ARC將此確定為開發(fā)者必須遵守的規(guī)則楼肪。
- ARC只負責管理Objective-C對象的內(nèi)存培廓。尤其要注意:CoreFoundation對象不歸ARC管理,開發(fā)者必須適時調(diào)用CFRetain/CFRelease春叫。
- 在dealloc方法中只釋放引用并解除監(jiān)聽
- 在dealloc方法里肩钠,應該做的事情就是釋放指向其它對象的引用泣港,并取消原來訂閱的鍵值觀測或NSNotificationCenter等通知,不要做其他事情价匠。
- 如果對象持有文件描述符等系統(tǒng)資源当纱,那么應該專門編寫一個方法來釋放此種資源。這樣的類要和其使用者約定“用完資源后必須調(diào)用close方法踩窖。
- 執(zhí)行異步任務的方法不應在dealloc里調(diào)用坡氯;只能在正常狀態(tài)下執(zhí)行的那些方法也不應在dealloc里調(diào)用,因為此時對象已處于正在回收的狀態(tài)了洋腮。
- 編寫異常安全代碼時留意內(nèi)存管理問題
- 捕獲異常時廉沮,一定要注意將try塊內(nèi)所創(chuàng)立的對象清理干凈。
- 在默認情況下徐矩,ARC不生成安全處理異常所需的清理代碼。開啟編譯器標志后叁幢,可生成這種代碼滤灯,不過會導致應用程序變大,而且會降低運行效率曼玩。
- 以弱引用避免重復引用
- 將某些引用設(shè)為weak鳞骤,可避免出現(xiàn)重復引用。
- weak引用可以自動清空黍判,也可以不自動清空豫尽。自動清空是隨著ARC而引入的新特性,由runtime來實現(xiàn)顷帖,在具備自動清空功能的弱引用上美旧,可以隨意讀取其數(shù)據(jù),因為這種引用不會指向已經(jīng)回收過的對象贬墩。
- 以自動釋放池塊降低內(nèi)存峰值
- 自動釋放池排布在棧中榴嗅,對象收到autorelease消息后,系統(tǒng)將其放入最頂端的池里陶舞。
- 合理運用自動釋放池嗽测,可降低應用程序的內(nèi)存峰值。
- @autoreleasepool這種新式寫法能創(chuàng)建出更為輕便的自動釋放池肿孵。
- 用“僵尸對象”調(diào)試內(nèi)存管理問題
- 系統(tǒng)在回收對象時唠粥,可以不將其真的回收,而是把它轉(zhuǎn)化為僵尸對象停做。通過環(huán)境變量NSZombieEnabled可開啟此功能晤愧。
- 系統(tǒng)會修改對象的isa指針,令其指向特殊的僵尸類蛉腌,從而使該對象變?yōu)榻┦瑢ο笱獭=┦惸軌蝽憫械膕elector響應方式為:打印一條包含消息內(nèi)容及其接受者的消息葵硕,然后終止應用程序。
- 不要使用retainCount
- 對象的保留計數(shù)看似有用贯吓,實則不然懈凹,因為任何給定時間點上的絕對保留計數(shù)都無法反映對象生命期的全貌。
- 引入ARC后悄谐,retainCount方法就正式廢止了介评,在ARC下調(diào)用該方法會導致編譯器報錯。
六爬舰、block與GCD
- 理解block的概念
- block是C们陆、C++、Objective-C中的詞法閉包情屹。
- block可接收參數(shù)坪仇,也可返回值。
- block可以分配在椑悖或堆上椅文,也可以是全局的。分配在棧上的block可拷貝到堆里惜颇,這樣的話皆刺,就和標準的Objective-C對象一樣,具備引用計數(shù)了凌摄。
- 為常用的block類型創(chuàng)建typedef
- 以typedef重新定義block類型羡蛾,可以令block變量用起來更加簡單。
- 定義新類型時應遵循現(xiàn)有的命名習慣锨亏,勿使其名稱與別的的類型相沖突痴怨。
- 不妨為同一個block簽名定義多個類型別名。如果要重構(gòu)的代碼使用了block類型的某個別名器予,那么只需修改相應的typedef中的block簽名即可腿箩,無需改動其他typedef。
- 用handler塊降低代碼分散程度
- 在創(chuàng)建對象時劣摇,使用內(nèi)聯(lián)的handler塊將相關(guān)業(yè)務邏輯一并聲明珠移。
- 在有多個實例需要監(jiān)控時,如果采用委托模式末融,那么經(jīng)常需要根據(jù)傳入的對象來切換钧惧,而若改用handler塊來實現(xiàn),則可直接將block與相關(guān)對象放在一起勾习。
- 設(shè)計API時如果用到了handler塊浓瞪,那么可以增加一個參數(shù),使調(diào)用者可通過此參數(shù)來決定應該把block安排在哪個隊列上執(zhí)行巧婶。
- 用block引用其所屬對象時不要出現(xiàn)循環(huán)引用
- 如果block所捕獲的對象直接或間接的保留了block本身乾颁,那么就得當心循環(huán)引用的問題涂乌。
- 一定要找個適當?shù)臅r機解除循環(huán)引用,而不能把責任推給API的調(diào)用者英岭。
- 多用派發(fā)隊列湾盒,少用同步鎖
- 派發(fā)隊列可用來表述同步語義,這種做法要比使用@synchronized塊或NSLock對象更簡單诅妹。
- 將同步與異步派發(fā)結(jié)合起來罚勾,可以實現(xiàn)與普通加鎖機制一樣的同步行為,而這么做卻不會阻塞執(zhí)行異步派發(fā)的線程吭狡。
- 使用同步隊列及柵欄塊尖殃,可以領(lǐng)同步行為更加高效。
- 多用GCD划煮,少用performSelector系列方法
- performSelector系列方法在內(nèi)存管理方面容易有疏失送丰。它無法確定將要執(zhí)行的selector具體是什么,因而ARC編譯器就無法插入適當?shù)膬?nèi)存管理方法弛秋。
- performSelector系列方法所能處理的selector太過局限了器躏,selector的返回值類型及發(fā)送給方法的參數(shù)個數(shù)都受到限制。
- 如果想把人物放在另一個線程上執(zhí)行铐懊,那么最好不要用performSelector系列方法而是應該把任務封裝到block里然后調(diào)用GCD機制的相關(guān)方法來實現(xiàn)。
- 掌握GCD及操作隊列的使用時機
- 在解決多線程與任務管理問題時瞎疼,派發(fā)隊列并非唯一方案科乎。
- 操作隊列提供了一套高層的Objective-C API,能實現(xiàn)純GCD所具備的絕大部分功能贼急,而且還能完成一些更為復雜的操作茅茂,那些操作若改用GCD來實現(xiàn),則需另外編寫代碼太抓。
- 通過Dispatch Group機制根據(jù)系統(tǒng)資源狀況來執(zhí)行任務
- 一系列任務可貴如一個dispatch group之中空闲。開發(fā)者可以在這組任務執(zhí)行完畢時獲得通知。
- 通過dispatch group走敌,可以在并發(fā)式派發(fā)隊列里同時執(zhí)行多項任務碴倾。此時GCD會根據(jù)系統(tǒng)資源狀況來調(diào)度這些并發(fā)執(zhí)行的任務。開發(fā)者若自己來實現(xiàn)此功能掉丽,則需編寫大量代碼跌榔。
- 使用dispatch_once來執(zhí)行只需運行一次的線程安全代碼
- 經(jīng)常需要編寫只需執(zhí)行一次的線程安全代碼。通過GCD所提供的dispatch_once函數(shù)捶障,很容易就能實現(xiàn)此功能僧须。
- 標記應該聲明在static或global作用域中,這樣的話项炼,在把只需執(zhí)行一次的block傳給dispatch_once函數(shù)時担平,傳進去的標記也是相同的示绊。
- 不要使用dispatch_get_current_queue
- dispatch_get_current_queue函數(shù)的行為常常與開發(fā)者所預期的不同。此函數(shù)已廢棄暂论,只應做調(diào)試之用面褐。
- 由于派發(fā)隊列是按層級來組織的,所以無法單用某個隊列對象來描述當前隊列這一概念空另。
- dispatch_get_current_queue函數(shù)用于解決由不可重入的代碼所引發(fā)的死鎖盆耽,然而能用此函數(shù)解決的問題,通常也能改用“隊列特定數(shù)據(jù)”來解決扼菠。
七摄杂、系統(tǒng)框架
- 熟悉系統(tǒng)框架
- 許多系統(tǒng)框架都可以直接使用。其中最重要的是Foundation與CoreFoundation循榆,這兩個框架提供了構(gòu)建應用程序所需的許多核心功能析恢。
- 很多常見任務都能用框架來做,例如音頻與視頻處理秧饮、網(wǎng)絡(luò)通信
數(shù)據(jù)管理等映挂。 - 請記住朝扼,用純C寫成的框架與用Objective-C寫成的一樣重要卖漫,若想成為優(yōu)秀的Objective-C開發(fā)者,應該掌握C語言的核心概念现诀。
- 多用塊枚舉泼各,少用for循環(huán)
- 遍歷collection有4種方式鞍时。最基本的辦法是for循環(huán),其次是NSEnumerator遍歷方法及快速遍歷方法扣蜻,最新逆巍、最先進的方式則是塊枚舉法。
- 塊枚舉法本身就能通過GCD來并發(fā)執(zhí)行遍歷操作莽使,無需另行編寫代碼锐极。而采用其他遍歷方式則無法輕易實現(xiàn)這一點。
- 若提前知道待遍歷的collection含有何種對象芳肌,則應修改塊簽名灵再,指出對象的具體類型。
- 隊自定義其內(nèi)存管理語義的collection使用無縫橋接
- 通過無縫橋接技術(shù)亿笤,可以在Foundation框架中的Objective-C對象與CoreFoundation框架中的C語言數(shù)據(jù)結(jié)構(gòu)之前來回轉(zhuǎn)換檬嘀。
- 在CoreFoundation層面創(chuàng)建collection時,可以指定許多回調(diào)函數(shù)责嚷,這些函數(shù)表示此collection應如何處理其元素鸳兽。然后,可運用無縫橋接技術(shù)罕拂,將其轉(zhuǎn)換成具備特殊內(nèi)存管理語義的Objective-C collection揍异。
- 構(gòu)建緩存是選用NSCachae而非NSDictionary
- 實現(xiàn)緩存時應選用NSCache而非NSDictionary對象全陨。因為NSCache可以提供優(yōu)雅的自動刪減功能,而且是線程安全的衷掷,此外辱姨,它與字典不同,并不會拷貝鍵戚嗅。
- 可以給NSCache對象設(shè)置上限雨涛,用以限制緩存中的對象總個數(shù)及總成本,而這些尺度則定義了緩存刪減其中對象的時機懦胞。但是絕對不要把這些尺度當成可靠的硬限制替久,他們僅對NSCache起指導作用。
- 將NSPurgeableData與NSCache搭配使用躏尉,可實現(xiàn)自動清除數(shù)據(jù)的功能蚯根,也就是說,當NSPurgeableData對象所占內(nèi)存為系統(tǒng)丟棄時胀糜,該對象自身也會從緩存中移除4.
- 如果緩存使用得當颅拦。那么應用程序的響應速度就能提高。只有那種重新計算起來很費事的數(shù)據(jù)教藻,才值得放入緩存距帅,比如那些需要從網(wǎng)絡(luò)獲取或從磁盤讀取的數(shù)據(jù)。
- 精簡initialize與load的實現(xiàn)代碼
- 在加載階段括堤,如果實現(xiàn)了load方法碌秸,那么系統(tǒng)就會調(diào)用它。分類里也可以定義此方法痊臭,類load方法要比分類中的先調(diào)用哮肚。與其他方法不同登夫,load方法不參與覆寫機制广匙。
- 首次使用某個類之前,系統(tǒng)會向其發(fā)送initialize消息恼策。由于此方法遵從普通的復寫規(guī)則鸦致,所以通常應該在里面判斷當前要初始化的是哪個類。
- load與initialize方法都應該實現(xiàn)的精簡一些涣楷,這有助于保持應用程序的響應能力分唾,也能減少引入依賴環(huán)的幾率。
- 無法在編譯期設(shè)定的全局常量狮斗,可以放在initialize方法里初始化绽乔。
- 別忘了NSTimer會保留其目標對象
- NSTimer對象會保留其目標,直到計時器本身失效為止碳褒,調(diào)用invalidate方法可令計時器失效折砸,另外看疗,一次性的計時器在觸發(fā)完任務之后也會失效。
- 反復執(zhí)行任務的計時器睦授,很容易引入循環(huán)引用两芳,進入過這種計時器的目標對象又保留了計時器本身,那肯定會導致循環(huán)引用去枷。這種循環(huán)引用怖辆,可能是直接發(fā)生的,也可能是通過對象圖里的其他對象間接發(fā)生的删顶。
- 可以擴充NSTimer的功能竖螃,用塊來打破循環(huán)引用。不過翼闹,除非NSTimer將來在公共接口里提供此功能斑鼻,否則必須創(chuàng)建分類,將相關(guān)實現(xiàn)代碼加入其中猎荠。