《Effective Objective-C 2.0》總結(jié)

編寫高質(zhì)量iOS與OS X代碼的52個(gè)有效方法

一稚机、熟悉Objective-C

1烧给、了解Objective-C語言的起源

* Objective-C為C語言添加了面向?qū)ο筇匦院熘瞧涑苎痢bjective-C使用動(dòng)態(tài)綁定的消息結(jié)構(gòu)贯城,也就是說加缘,在運(yùn)行時(shí)才會(huì)檢查對象類型鸭叙。接收一條消息之后,究竟應(yīng)執(zhí)行何種代碼拣宏,由運(yùn)行期環(huán)境而非編譯器來決定沈贝。

* 理解C語言的核心概念有助于寫好Objective-C程序。尤其要掌握內(nèi)存模型與指針勋乾。

2宋下、在類的頭文件中盡量少引入其他頭文件

* 除非確有必要,否則不要引入頭文件辑莫。一般來說学歧,應(yīng)在某個(gè)類的頭文件中使用向前聲明來提及別的類,并在實(shí)現(xiàn)文件中引入那些類的頭文件各吨。這樣做可以盡量降低類之間的耦合(coupling)枝笨。

* 有時(shí)無法使用向前聲明,比如要聲明某個(gè)類遵循一項(xiàng)協(xié)議揭蜒。這種情況下横浑,盡量把“該類遵循某協(xié)議”的這條聲明移至“class-continuation分類”中。如果不行的話忌锯,就把協(xié)議單獨(dú)放在一個(gè)頭文件中伪嫁,然后將其引入。

3偶垮、多用字面量語法张咳,少用與之等價(jià)的方法

* 應(yīng)該使用字面量語法來創(chuàng)建字符串、數(shù)值似舵、數(shù)組脚猾、字典。與創(chuàng)建此類對象的常規(guī)方法相比砚哗,這么做更加簡明扼要龙助。

* 應(yīng)該通過取下標(biāo)操作來訪問數(shù)組下標(biāo)或字典中鍵所對應(yīng)的元素。

* 用字面量語法創(chuàng)建數(shù)組或字典時(shí),若值中有nil提鸟,則會(huì)拋出異常军援。因此,務(wù)必確保值里不含nil称勋。

4胸哥、多用類型常量,少用#define預(yù)處理指令

* 不要用預(yù)處理指令定義常量赡鲜。這樣定義出來的常量不含類型信息空厌,編譯器只是會(huì)在編譯前據(jù)此執(zhí)行查找與替換操作。即使有人重新定義了常量值银酬,編譯器也不會(huì)產(chǎn)生警告信息嘲更,這將導(dǎo)致應(yīng)用程序中的常量值不一致。

* 在實(shí)現(xiàn)文件中使用static const來定義“只在編譯單元內(nèi)可見的常量”(translation-unit-specific constant)揩瞪。由于此類常量不在全局符號(hào)表中赋朦,所以無需為其名稱加前綴。

* 在頭文件中使用extern來聲明全局變量李破,并在相關(guān)實(shí)現(xiàn)文件中定義其值北发。這種常量要出現(xiàn)在全局符號(hào)表中,所以其名稱應(yīng)加以區(qū)隔喷屋,通常用與之相關(guān)的類名做前綴琳拨。

5、枚舉表示狀態(tài)屯曹、選項(xiàng)狱庇、狀態(tài)碼

* 應(yīng)該用枚舉來表示狀態(tài)機(jī)的狀態(tài)、傳遞給方法的選項(xiàng)以及狀態(tài)碼等值恶耽,給這些值起個(gè)易懂的名字密任。

* 如果把傳遞給某個(gè)方法的選項(xiàng)表示枚舉類型,而多個(gè)選項(xiàng)又可同時(shí)使用偷俭,那么就將各選項(xiàng)值定義為2的冪浪讳,以便通過按位或操作將其組合起來。

* 用NS_ENUM與NS_OPTIONS宏來定義枚舉類型涌萤,并指明其底層數(shù)據(jù)類型淹遵。這樣做可以確保枚舉是用開發(fā)者所選的底層數(shù)據(jù)類型實(shí)現(xiàn)出來的,而不是采用編譯器所選的類型负溪。

* 在處理枚舉類型的switch語句中不要實(shí)現(xiàn)default分支透揣。這樣的話,加入新枚舉之后川抡,編譯器就會(huì)提示開發(fā)者:switch語句并未處理所有枚舉辐真。

二、對象、消息侍咱、運(yùn)行期

6耐床、理解“屬性”這一概念

* 可用@property語法來定義對象中所封裝的數(shù)據(jù)。

* 通過“特質(zhì)”來指定存儲(chǔ)數(shù)據(jù)所需的正確語義楔脯。

* 在設(shè)置屬性所對應(yīng)的實(shí)例變量時(shí)咙咽,一定要遵從該屬性所聲明的語義。

* 開發(fā)iOS程序時(shí)應(yīng)該使用nonatomic屬性淤年,因?yàn)閍tomic屬性會(huì)嚴(yán)重影響性能。

7蜡豹、在對象內(nèi)部盡量直接訪問實(shí)例變量

* 在對象內(nèi)部讀取數(shù)據(jù)時(shí)麸粮,應(yīng)該直接通過實(shí)例變量來讀,而寫入數(shù)據(jù)時(shí)镜廉,則應(yīng)通過屬性來寫弄诲。

* 在初始化方法及dealloc方法中,總是應(yīng)該直接通過實(shí)例變量來讀寫數(shù)據(jù)娇唯。

* 有時(shí)會(huì)使用惰性初始化技術(shù)配置某份數(shù)據(jù)齐遵,這種情況下,需要通過屬性來讀取數(shù)據(jù)塔插。

8梗摇、理解“對象等同性”這一概念

* 若想檢測對象的等同性,請?zhí)峁癷sEqual:”與hash方法想许。

* 相同的對象必須具有相同的哈希碼伶授,但是兩個(gè)哈希碼相同的對象未必相同。

* 不要盲目地逐個(gè)檢測每個(gè)屬性流纹,而是應(yīng)該依照具體需求來制定檢測方案糜烹。

* 編寫hash方法時(shí),應(yīng)該使用計(jì)算速度而且哈希碼碰撞幾率低的算法漱凝。

9疮蹦、以“類族模式”隱藏實(shí)現(xiàn)細(xì)節(jié)

* 類族模式可以把實(shí)現(xiàn)細(xì)節(jié)隱藏在一套簡單的公共接口后面。

* 系統(tǒng)框架中經(jīng)常使用類族茸炒。

* 從類族的公共抽象基類中繼承子類時(shí)要當(dāng)心愕乎,若有開發(fā)文檔,則應(yīng)首先閱讀壁公。

10妆毕、在既有類中使用關(guān)聯(lián)對象存放自定義數(shù)據(jù)

* 可以通過“關(guān)聯(lián)對象”機(jī)制來把兩個(gè)對象連起來

* 定義關(guān)聯(lián)對象時(shí)可指定內(nèi)存管理語義,用以模仿定義屬性時(shí)所采用的“擁有關(guān)系”與“非擁有關(guān)系”贮尖。

* 只有在其他做法不可行時(shí)才應(yīng)選用關(guān)聯(lián)對象笛粘,因?yàn)檫@種做法通常會(huì)引入難于查找的bug

11、理解 objc_msgSend 的作用

* 消息由接收者、選擇子及參數(shù)構(gòu)成薪前。給某對象“發(fā)送消息”(invoke a message)也就是相當(dāng)于在該對象上“調(diào)用方法”(call a method)润努。

* 發(fā)給某對象的全部消息都要由“動(dòng)態(tài)消息派發(fā)系統(tǒng)”(dynamic message dispatch system)來處理,該系統(tǒng)會(huì)查出對應(yīng)的方法示括,并執(zhí)行其代碼铺浇。

12、理解消息轉(zhuǎn)發(fā)機(jī)制

* 若對象無法響應(yīng)某個(gè)選擇子垛膝,則進(jìn)入消息轉(zhuǎn)發(fā)流程

* 通過運(yùn)行期的動(dòng)態(tài)方法解析功能鳍侣,我們可以在需要用到某個(gè)方法時(shí)再將其加入類中。

* 對象可以把其無法解讀的某型選擇子轉(zhuǎn)交給其他對象來處理吼拥。

* 經(jīng)過上述兩步之后倚聚,如果還是沒辦法處理選擇子,那就啟動(dòng)完整的消息轉(zhuǎn)發(fā)機(jī)制

13凿可、用“方法調(diào)配技術(shù)”調(diào)試“黑盒方法”

* 使用另一份實(shí)現(xiàn)來替換原有的方法實(shí)現(xiàn)惑折,這道工序叫做“方法調(diào)配”,開發(fā)者常用此技術(shù)向原有實(shí)現(xiàn)中添加新功能枯跑。

* 一般來說惨驶,只有調(diào)試程序的時(shí)候才需要在運(yùn)行期修改方法實(shí)現(xiàn),這種做法不宜濫用敛助。

14粗卜、理解“類對象”的用意

* 每個(gè)實(shí)例都有一個(gè)指向 Class 對象的的指針,用以表明其類型纳击,而這些 Class 對象則構(gòu)成了類的繼承體系

* 如果對象類型無法在編譯期確定休建,那么就應(yīng)該使用類型信息查詢方法來探知。

* 盡量使用類型信息查詢方法來確定對象類型评疗,而不要直接比較對象测砂,因?yàn)槟承ο罂赡軐?shí)現(xiàn)了消息轉(zhuǎn)發(fā)功能

三、接口與API設(shè)計(jì)

15百匆、用前綴避免命名空間沖突

* 選擇與你的公司砌些、應(yīng)用程序或二者皆有關(guān)聯(lián)之名稱作為類名的前綴,并在所有代碼中均使用這一前綴

* 若自己所開發(fā)的程序中用到了第三方庫加匈,則應(yīng)為其中的名稱加上前綴存璃。

16、提供“全能初始化方法”

* 在類中提供一個(gè)全能初始化方法雕拼,并于文檔里指明纵东。其他初始化方法均應(yīng)用調(diào)用此方法。

* 若全能初始化方法與超類不同啥寇,則需覆寫超類中的對應(yīng)方法

* 如果超類的初始化方法不適用于子類偎球,那么應(yīng)該覆寫這個(gè)超類方法洒扎,并在其中拋出異常

17、實(shí)現(xiàn) description 方法

* 實(shí)現(xiàn) description 方法返回一個(gè)有意義的字符串衰絮,用以描述該實(shí)例

* 若想在調(diào)試時(shí)打印出更詳盡的對象描述信息袍冷,則應(yīng)實(shí)現(xiàn) debugDescription 方法

18、盡量使用不可變對象

* 盡量創(chuàng)建不可變的對象

* 若某屬性僅可于對象內(nèi)部修改猫牡,則在“class-continuation 分類”中將其由 readonly 屬性擴(kuò)展為 readwrite 屬性胡诗。

* 不要把可變的 collection 作為屬性公開,而應(yīng)提供相關(guān)方法淌友,以此修改對象中的可變 collection煌恢。

19、使用清晰而協(xié)調(diào)的命名方式

* 起名時(shí)應(yīng)遵從標(biāo)準(zhǔn)的 Objective-C 命名規(guī)范震庭,這樣創(chuàng)建出來的接口更容易為開發(fā)者所理解瑰抵。

* 方法名要言簡意賅,從左至右讀起來要像個(gè)日常用語中的句子才好

* 方法名里不要使用縮略后的類型名稱

* 給方法起名時(shí)的第一要?jiǎng)?wù)就是確保其風(fēng)格與你自己的代碼或所要集成的框架相符归薛。

20、為私有方法名加前綴

* 給私有方法的名稱加上前綴匪蝙,這樣可以很容易將其同公共方法區(qū)分開主籍。

* 不要單用一個(gè)下劃線做私有方法的前綴,因?yàn)檫@種做法是預(yù)留給蘋果公司用的逛球。

21千元、理解 Objective-C 錯(cuò)誤模型

* 只有發(fā)生了可使整個(gè)應(yīng)用程序崩潰的嚴(yán)重錯(cuò)誤時(shí),才應(yīng)使用異常颤绕。

* 在錯(cuò)誤不那么嚴(yán)重的情況下幸海,可以指派“委托方法”(delegate method)來處理錯(cuò)誤,也可以把錯(cuò)誤信息放在 NSEorror 對象里奥务,經(jīng)由“輸出參數(shù)”返回給調(diào)用者物独。

22、理解 NSCopying 協(xié)議

*? 若想令自己所寫的對象具有拷貝功能氯葬,則需要實(shí)現(xiàn) NSCopying 協(xié)議挡篓。

* 如果自定義的對象分為可變版本與不可變版本,那么就要同時(shí)實(shí)現(xiàn) NSCopying 與 NSMutableCopying 協(xié)議帚称。

* 復(fù)制對象時(shí)需要決定采用淺拷貝還是深拷貝官研,一般情況下應(yīng)該盡量執(zhí)行淺拷貝。

* 如果你所寫的對象需要深拷貝闯睹,那么可以考慮新增一個(gè)專門執(zhí)行深拷貝的方法戏羽。

四、協(xié)議與分類

23楼吃、通過委托與數(shù)據(jù)源協(xié)議進(jìn)行對象間通信

* 將委托對象應(yīng)該支持的接口定義成協(xié)議始花,在協(xié)議中把可能需要處理的事件定義成方法妄讯。

* 當(dāng)某對象需要另外一個(gè)對象中獲取數(shù)據(jù)時(shí),可以使用委托模式衙荐。這種情境下捞挥,該模式亦稱“數(shù)據(jù)源協(xié)議”(data source protocal)

* 若有必要,可實(shí)現(xiàn)含有段位的結(jié)構(gòu)體忧吟,將委托對象是否能響應(yīng)相關(guān)協(xié)議方法這一信息緩存至其中

24砌函、將類的實(shí)現(xiàn)代碼分散到便于管理的數(shù)個(gè)分類之中

* 使用分類機(jī)制把類的實(shí)現(xiàn)代碼劃分成易于管理的小塊

* 將應(yīng)該視為“私有”的方法歸入名叫 Private 分類中,以隱藏實(shí)現(xiàn)細(xì)節(jié)

25溜族、總是為第三方類的分類名稱加前綴

* 向第三方類中添加分類時(shí)讹俊,總應(yīng)給其名稱加上你的專用的前綴

* 向第三方類中添加分類時(shí),總應(yīng)給其中的方法名加上你專用的前綴

26煌抒、勿在分類匯總聲明屬性

* 把封裝數(shù)據(jù)所用的全部屬性都定義在主接口里

* 在“class-continuation 分類”之外的其他分類中仍劈,可以定義存取方法,但盡量不要定義屬性

27寡壮、使用“class-continuation 分類”隱藏實(shí)現(xiàn)細(xì)節(jié)

* 通過“class-continuation 分類”向類中新增實(shí)例變量贩疙。

* 如果某屬性在主接口中聲明為“只讀”,而類的內(nèi)部又要用設(shè)置方法修改此屬性况既,那么就在“class-continuation 分類”中將其擴(kuò)展為“可讀寫”这溅。

* 把私有方法的原型聲明在“class-continuation 分類”里面。

* 若想使類所遵循的協(xié)議不為所知棒仍,則可于“class-continuation 分類”中聲明悲靴。

28、通過協(xié)議提供匿名對象

* 協(xié)議可在某種程度上提供匿名類型莫其。具體的對象類型可以淡化稱遵從某協(xié)議的 id 類型癞尚,協(xié)議里規(guī)定了對象所應(yīng)實(shí)現(xiàn)的方法。

* 使用匿名對象來隱藏類型名稱(或類名)乱陡。

* 如果具體類型不重要浇揩,重要的是對象能夠響應(yīng)(定義在協(xié)議里的)特定方法,那么可使用匿名對象來表示憨颠。

五临燃、內(nèi)存管理

29、理解引用計(jì)數(shù)

* 引用計(jì)數(shù)機(jī)制可以遞增遞減的計(jì)數(shù)器來管理內(nèi)存烙心。對象創(chuàng)建好之后膜廊,其保留計(jì)數(shù)至少為1。若保留計(jì)數(shù)為正淫茵,則對象繼續(xù)存活爪瓜。當(dāng)保留計(jì)數(shù)降為0時(shí),對象就被銷毀了匙瘪。

* 在對象生命期中铆铆,其余對象通過引用來保留或釋放此對象蝶缀。保留與釋放操作分別會(huì)遞增及遞減保留計(jì)數(shù)。

30薄货、以 ARC 簡化引用計(jì)數(shù)

* 在 ARC 之后翁都,程序員就無須擔(dān)心內(nèi)存管理問題了。使用 ARC 來編程谅猾,可省去類中的許多“樣板代碼”柄慰。

* ARC 管理對象生命期的辦法基本上就是:在合適的地方插入“保留”及“釋放”操作。在 ARC 環(huán)境下税娜,變量的內(nèi)存管理語義可以通過修飾符指明坐搔,而原來則需要手工執(zhí)行“保留”及“釋放”操作。

* 由方法所返回的對象敬矩,其內(nèi)存管理語義總是通過方法名來體現(xiàn)概行。ARC 將此確定為開發(fā)者必須遵循的規(guī)則。

* ARC 只負(fù)責(zé)管理 Objective-C 對象的內(nèi)存弧岳。尤其要注意:CoreFoundation 對象不歸 ARC 管理凳忙,開發(fā)者必須適時(shí)調(diào)用 CFRetain/CFRelease。

31禽炬、在dealloc 方法中只釋放引用并解除監(jiān)聽

* 在dealloc方法里涧卵,應(yīng)該做的事情就是釋放指向其他對象的引用,并取消原來訂閱的“鍵值觀測”(KVO)或 NSNotificationCenter 等通知瞎抛,不要做其他事情艺演。

* 如果對象持有文件描述符等系統(tǒng)資源却紧,那么應(yīng)該專門編寫一個(gè)方法來釋放此種資源桐臊。這樣的類要和其使用者約定:用完資源后必須調(diào)用 close 方法。

* 執(zhí)行異步任務(wù)的方法不應(yīng)在dealloc 里調(diào)用晓殊;只能在正常狀態(tài)下執(zhí)行的那些方法也不應(yīng)在dealloc 里調(diào)用断凶。

32、編寫“異步安全代碼”時(shí)留意內(nèi)存管理問題

* 捕獲異常時(shí)巫俺,一定要注意將 try 塊內(nèi)所創(chuàng)立的對象清理干凈认烁。

* 在默認(rèn)情況下,ARC 不生成安全處理異常所需要的清理代碼介汹。開啟編譯器標(biāo)志后却嗡,可生成這種代碼,不過會(huì)導(dǎo)致應(yīng)用程序變大嘹承,而且會(huì)降低運(yùn)行效率窗价。

33、以弱引用避免保留環(huán)

* 將某些引用設(shè)為 weak叹卷,可避免出現(xiàn)“保留環(huán)”撼港。

* weak 引用可以自動(dòng)清空坪它,也可以不自動(dòng)清空。自動(dòng)清空(autonilling)是隨著 ARC 而引入的新特性帝牡,由運(yùn)行期系統(tǒng)來實(shí)現(xiàn)往毡。在具備自動(dòng)清空功能的弱引用上,可以隨意讀取其數(shù)據(jù)靶溜,因?yàn)檫@種引用不會(huì)指向已經(jīng)回收過的對象开瞭。

34、以“自動(dòng)釋放池”降低內(nèi)存峰值

* 自動(dòng)釋放池排布在棧中墨技,對象收到 autorelease 消息后惩阶,系統(tǒng)將其放入最頂端的池里。

* 合理運(yùn)用自動(dòng)釋放池扣汪,可降低應(yīng)用程序的內(nèi)存峰值断楷。

* @autoreleasepool 這種新式寫法能創(chuàng)建出更為輕便的自動(dòng)釋放池。

35崭别、用“僵尸對象”調(diào)試內(nèi)存管理問題

* 系統(tǒng)在回收對象時(shí)冬筒,可以不將其真的回收,而是把它轉(zhuǎn)化為僵尸對象茅主。通過環(huán)境變量 NSZombieEnable 可開啟此功能舞痰。

* 系統(tǒng)會(huì)修改對象的 isa 指針,令其指向特殊的僵尸類诀姚,從而使該對象變?yōu)榻┦瑢ο笙炫!=┦惸軌蝽憫?yīng)所有的選擇子,響應(yīng)方式為:打印一條包含消息內(nèi)容及其接收者的消息赫段,然后終止應(yīng)用程序呀打。

36、不要使用 retainCount

* 對象的把保留計(jì)數(shù)看似有用糯笙,實(shí)則不然贬丛,因?yàn)槿魏谓o定時(shí)間上的“絕對保留計(jì)數(shù)”(absolute retain count)都無法反映對象生命期的全貌芜果。

* 引入 ARC 之后嵌言,retainCount 方法就正式廢止了熏矿,在 ARC 下調(diào)用該方法會(huì)導(dǎo)致編譯器報(bào)錯(cuò)王凑。

六山林、塊與大中樞派發(fā)

37伍伤、理解“塊”這一概念

* 塊是 C沧烈、C++阴孟、Objective-C 中的詞法閉包

* 塊可接受參數(shù)耘眨,也可返回值昼榛。

* 塊可以分配在棧或堆上毅桃,也可以是全局的褒纲。分配在棧上的塊可拷貝到堆里准夷,這樣的話,就和標(biāo)準(zhǔn)的 Objective-C 對象一樣莺掠,具備引用計(jì)數(shù)了衫嵌。

38、為常用的塊類型創(chuàng)建 typedef

* 以 typedef 重新定義塊類型彻秆,可令變量用起來更加簡潔楔绞。

* 定義新類型時(shí)應(yīng)遵從現(xiàn)有的命名習(xí)慣,勿使用其名稱與別的類型相沖突唇兑。

* 不妨為同一個(gè)塊簽名定義多個(gè)類型別名酒朵。如果要重構(gòu)的代碼使用了塊類型的某個(gè)別稱,那么只需修改相應(yīng) typedef 中的塊標(biāo)簽名即可扎附,無須改動(dòng)其他 typedef蔫耽。

39、用 handler 塊降低代碼分散程度

* 在創(chuàng)建對象時(shí)留夜,可以使用內(nèi)聯(lián)的 handler 塊將相關(guān)業(yè)務(wù)邏輯一并聲明匙铡。

* 在有多個(gè)實(shí)例需要監(jiān)控時(shí),如果采用委托模式碍粥,那么經(jīng)常需要根據(jù)傳入的對象來切換鳖眼,而若改用 handler 塊來實(shí)現(xiàn),則可直接將塊與相關(guān)對象放在一起嚼摩。

* 設(shè)計(jì) API 時(shí)如果用到了 handler 塊钦讳,那么可以增加一個(gè)參數(shù),使調(diào)用者可通過此參數(shù)來決定應(yīng)該把塊安排在哪個(gè)隊(duì)列上執(zhí)行枕面。

40愿卒、用塊引用其所屬對象時(shí)不要出現(xiàn)保留環(huán)

* 如果塊所捕捉的對象直接或間接地保留了塊的本身,那么就得當(dāng)心保留環(huán)問題膊畴。

* 一定要找個(gè)適當(dāng)?shù)臅r(shí)機(jī)解除保留環(huán)掘猿,而不能把責(zé)任推給 API 的調(diào)用者病游。

41唇跨、多用派發(fā)隊(duì)列,少用同步鎖

* 派發(fā)隊(duì)列可用來表述同步語義(synchronization semantic)衬衬,這種做法要比使用@synchronized 塊或NSLock 對象更簡單买猖。

* 將同步與異步派發(fā)結(jié)合起來,可以實(shí)現(xiàn)與普通加鎖機(jī)制一樣的同步行為滋尉,而這么做卻不會(huì)阻塞執(zhí)行異步派發(fā)的線程玉控。

* 使用同步隊(duì)列及柵欄塊,可以令同步行為更加高效狮惜。

42高诺、多用 GCD碌识,少用 performSelector 系列方法

* performSelector 系列方法在內(nèi)存管理方面容易有疏失。它無法確定將要執(zhí)行的選擇子具體是什么虱而,因而 ARC 編譯器也就無法插入適當(dāng)?shù)膬?nèi)存管理方法筏餐。

* performSelector 系列方法所能處理的選擇子太過局限了,選擇子的返回值類型及發(fā)送給方法的參數(shù)個(gè)數(shù)都受到限制牡拇。

* 如果想把任務(wù)放在另一個(gè)線程上執(zhí)行魁瞪,那么最好不要用 performSelector 系列方法,而是應(yīng)該把任務(wù)封裝到這里然后調(diào)用大中樞派發(fā)機(jī)制的相關(guān)方法來實(shí)現(xiàn)惠呼。

43导俘、掌握 GCD 及操作隊(duì)列的使用時(shí)機(jī)

* 在解決多線程與任務(wù)管理問題時(shí)派發(fā)隊(duì)列并非唯一方案

* 操作隊(duì)列提供了一套高層的 Objective-C API,能實(shí)現(xiàn)純 GCD 所具備的絕大部分功能剔蹋,而且還能完成一些更為復(fù)雜的操作旅薄,那些操作若改用 GCD 來實(shí)現(xiàn),則需要另外編寫代碼泣崩。

44赋秀、通過 Dispatch Croup 機(jī)制,根據(jù)系統(tǒng)資源狀態(tài)來執(zhí)行任務(wù)

* 一系列任務(wù)可歸入一個(gè) dispatch group 之中律想,開發(fā)者可以在這組任務(wù)執(zhí)行完畢時(shí)獲得通知猎莲。

* 通過dispatch group,可以在并發(fā)式派發(fā)隊(duì)列里同時(shí)執(zhí)行多項(xiàng)任務(wù)技即。此時(shí) GCD 會(huì)根據(jù)系統(tǒng)資源狀況來調(diào)度這些并發(fā)執(zhí)行的任務(wù)著洼。開發(fā)者若自己來實(shí)現(xiàn)此功能,則需要編寫大量代碼而叼。

45身笤、使用 dispatch_once 來執(zhí)行只需運(yùn)行一次的線程安全代碼

* 經(jīng)常需要編寫“只需執(zhí)行一次的線程安全代碼”(thread-safe single-code execution)。通過 GCD 所提供的 dispatch_once 函數(shù)葵陵,很容易就能實(shí)現(xiàn)此功能液荸。

* 標(biāo)記應(yīng)該聲明在 static 或 global 作用域中,這樣的話脱篙,在把只需執(zhí)行一次的塊傳給 dispatch_once 函數(shù)時(shí)娇钱,傳進(jìn)去的標(biāo)記也是相同的。

46绊困、不要使用 dispatch_get_current_queue

* dispatch_get_current_queue 函數(shù)的行為常常與開發(fā)者所預(yù)期的不同文搂。此函數(shù)已經(jīng)廢棄,只應(yīng)做調(diào)試之用秤朗。

* 由于派發(fā)隊(duì)列示按層級(jí)來組織的煤蹭,所以無法單用某個(gè)隊(duì)列對象來描述“當(dāng)前隊(duì)列”這一概念。

* dispatch_get_current_queue 函數(shù)用于解決由不可重入的代碼所引發(fā)的死鎖,然而能用此函數(shù)解決的問題硝皂,通常也能改用“隊(duì)列特定數(shù)據(jù)”來解決常挚。

七、系統(tǒng)框架

47稽物、熟悉系統(tǒng)框架

* 許多系統(tǒng)框架都可以直接使用待侵。其中最重要的是 Foundation 與 CoreFoundation,這兩個(gè)框架提供了構(gòu)建應(yīng)用程序所需的許多核心功能姨裸。

* 很多常見任務(wù)都能用框架來做秧倾,例如音頻與視頻處理、網(wǎng)絡(luò)通信傀缩、數(shù)據(jù)管理等那先。

* 請記住:用純 C 寫成的框架與用 Objective-C 寫成的一樣重要赡艰,若想成為優(yōu)秀的 Objective-C開發(fā)者售淡,應(yīng)該掌握 C 語言的核心概念。

48慷垮、多用塊枚舉揖闸,少用 for 循環(huán)

* 遍歷 collection 有四種方式。最基本的辦法是 for 循環(huán)料身,其次是 NSEnumerator 遍歷法及快速遍歷法汤纸,最新、最先進(jìn)的方式則是“塊枚舉法”芹血。

* “塊枚舉法”本身就能通過 GCD 來并發(fā)執(zhí)行遍歷操作贮泞,無須另行編寫代碼。而采用其他遍歷方式則無法輕易實(shí)現(xiàn)這一點(diǎn)幔烛。

* 若提前知道待遍歷的 collection 含有何種對象啃擦,則應(yīng)修改塊簽名,指出對象的具體類型饿悬。

49令蛉、對自定義其內(nèi)存管理語義的 collection 使用無縫橋接

* 通過無縫橋接技術(shù),可以在 Foundation 框架中的 Objective-C 對象與 CoreFoundation 框架中的 C 語言數(shù)據(jù)結(jié)構(gòu)之間來回轉(zhuǎn)換狡恬。

* 在 CoreFoundation 層面創(chuàng)建 collection 時(shí)珠叔,可以指定許多回調(diào)函數(shù),這些函數(shù)表示此 collection 應(yīng)如何處理其元素傲宜。然后运杭,可運(yùn)用無縫橋接技術(shù)夫啊,將其轉(zhuǎn)換成具備特殊內(nèi)存管理語義的 Objective-C collection函卒。

50、構(gòu)建緩存時(shí)選用 NSCache 而非 NSDictionary

* 實(shí)現(xiàn)緩存時(shí)應(yīng)選用 NSCache 而非 NSDictionary 對象。因?yàn)?NSCache 可以提供優(yōu)雅自動(dòng)刪減功能报嵌,而且是“線程安全的”虱咧,此外,它與字典不同锚国,并不會(huì)拷貝鍵腕巡。

* 可以給 NSCache 對象設(shè)置上限,用以限制緩存中的對象總個(gè)數(shù)及“總成本”血筑,而這些尺度則定義了緩存刪減其中對象的時(shí)機(jī)绘沉。但是絕對不要把這些尺度當(dāng)成可靠的“硬限制”(hard limit),它們僅對 NSCache 起指導(dǎo)作用豺总。

* 將 NSPurgeableData 與 NSCache 搭配使用车伞,可實(shí)現(xiàn)自動(dòng)清除數(shù)據(jù)的功能,也就是說喻喳,當(dāng) NSPurgeableData 對象所占內(nèi)存為系統(tǒng)所丟棄時(shí)另玖,該對象自身也會(huì)從緩存中移除。

* 如果緩存使用得當(dāng)表伦,那么應(yīng)用程序的響應(yīng)速度就能提高谦去。只有那種“重新計(jì)算起來很費(fèi)事的”數(shù)據(jù),才值得放入緩存蹦哼,比如那些需要從網(wǎng)絡(luò)獲取或從磁盤讀取的數(shù)據(jù)鳄哭。

51、精簡 initialize 與 load 的實(shí)現(xiàn)代碼

* 在加載階段纲熏,如果類實(shí)現(xiàn)了 load 方法窃诉,那么系統(tǒng)就會(huì)調(diào)用它。分類里也可以定義此方法赤套,類的 load 方法要比分類中的先調(diào)用飘痛。與其他方法不同,load 方法不參與覆寫機(jī)制容握。

* 首次使用某個(gè)類之前宣脉,系統(tǒng)會(huì)向其發(fā)送 initialize 消息。由于此方法遵從普通的覆寫規(guī)則剔氏,所以通常應(yīng)該在里面判斷當(dāng)前要初始化的是哪個(gè)類塑猖。

* load 與 initialize 方法都應(yīng)該實(shí)現(xiàn)得精簡一些,這有助于保持應(yīng)用程序的響應(yīng)能力谈跛,也能減少引入“依賴環(huán)”(interdependecy cycle)的幾率羊苟。

* 無法在編譯其設(shè)定的全局常量,可以放在initialize 方法里初始化感憾。

52蜡励、別忘了 NSTimer 會(huì)保留其目標(biāo)對象

* NSTimer 對象會(huì)保留其目標(biāo),直到計(jì)時(shí)器本身失效為止,調(diào)用 invalidate 方法可令計(jì)時(shí)器失效凉倚,另外兼都,一次性的計(jì)時(shí)器在觸發(fā)完任務(wù)之后也會(huì)失效。

* 反復(fù)執(zhí)行任務(wù)的計(jì)時(shí)器(repeating timer)稽寒,很容易引入保留環(huán)扮碧,如果這種計(jì)時(shí)器的目標(biāo)對象又保留了計(jì)時(shí)器本身,那肯定會(huì)導(dǎo)致保留環(huán)杏糙。這種環(huán)狀保留關(guān)系慎王,可能是直接發(fā)生的,也可能是通過對象圖里的其他對象間接發(fā)生的宏侍。

* 可以擴(kuò)充 NSTimer 的功能柬祠,用“塊”來打破保留環(huán)。不過负芋,除非 NSTimer 將來在公共接口里提供此功能漫蛔,否則必須創(chuàng)建分類,將相關(guān)實(shí)現(xiàn)代碼加入其中旧蛾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末莽龟,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子锨天,更是在濱河造成了極大的恐慌毯盈,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件病袄,死亡現(xiàn)場離奇詭異搂赋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)益缠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門脑奠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人幅慌,你說我怎么就攤上這事宋欺。” “怎么了胰伍?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵齿诞,是天一觀的道長。 經(jīng)常有香客問我骂租,道長祷杈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任渗饮,我火速辦了婚禮但汞,結(jié)果婚禮上宿刮,老公的妹妹穿的比我還像新娘。我一直安慰自己特占,他們只是感情好糙置,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布云茸。 她就那樣靜靜地躺著是目,像睡著了一般。 火紅的嫁衣襯著肌膚如雪标捺。 梳的紋絲不亂的頭發(fā)上懊纳,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音亡容,去河邊找鬼嗤疯。 笑死,一個(gè)胖子當(dāng)著我的面吹牛闺兢,可吹牛的內(nèi)容都是我干的茂缚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼屋谭,長吁一口氣:“原來是場噩夢啊……” “哼脚囊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起桐磁,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤悔耘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后我擂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衬以,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年校摩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了看峻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡衙吩,死狀恐怖备籽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情分井,我是刑警寧澤车猬,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站尺锚,受9級(jí)特大地震影響珠闰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瘫辩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一伏嗜、第九天 我趴在偏房一處隱蔽的房頂上張望坛悉。 院中可真熱鬧,春花似錦承绸、人聲如沸裸影。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽轩猩。三九已至,卻和暖如春荡澎,著一層夾襖步出監(jiān)牢的瞬間均践,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國打工摩幔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留彤委,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓或衡,卻偏偏與公主長得像焦影,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子封断,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 《摔跤吧澄港!爸爸》椒涯,這是一部十分好看的電影,里面的劇情時(shí)而令人驚心動(dòng)魄回梧,時(shí)而令人感動(dòng)废岂;時(shí)而令人產(chǎn)生期望,時(shí)而...
    丁心哲閱讀 267評(píng)論 0 0
  • 歌詞里說愛的路有千萬條狱意,借用到育兒上很是恰當(dāng)湖苞。 張三說,青春是拿來拼的详囤,拼好十六年财骨,幸福六十年。...
    雪藏小屋閱讀 648評(píng)論 0 0
  • 我不讓你走藏姐,因?yàn)槲抑滥悴粫?huì)走隆箩。除去生死,我不準(zhǔn)你離開我很久羔杨,除在我身邊捌臊,你還在我心里、腦袋里兜材、眼里理澎,血液里逞力、空氣...
    7號(hào)禁藥閱讀 673評(píng)論 0 1
  • 盤坐于墊子上,雙腿伸直糠爬。 抬起右腳跨過左膝寇荧,腳掌踩地,將你的大腿往腹部靠近一些执隧,左腳尖回勾揩抡。 左手向上,呼氣殴玛,往前...
    aily群閱讀 3,382評(píng)論 0 0