<h3>第1章 熟悉Objective-C</h3>
<h4>第1條:了解OC語(yǔ)言的起源</h4>
要點(diǎn):
1.OC為C語(yǔ)言添加了面向?qū)ο筇匦裕瞧涑?。OC使用動(dòng)態(tài)綁定的消息結(jié)構(gòu),也就是說(shuō),在運(yùn)行時(shí)才會(huì)檢查對(duì)象類型。接收一條消息之后,究竟應(yīng)執(zhí)行何種代碼,由運(yùn)行期環(huán)境而非編譯器來(lái)決定。
2.理解C語(yǔ)言的核心概念有助于寫好OC程序。尤其要掌握內(nèi)存模型與指針。
<h4>第2條:在類的頭文件中盡量少引入其他頭文件</h4>
@class 向前引用
要點(diǎn):
1.除非確有必要,否則不要引入頭文件。一般來(lái)說(shuō),應(yīng)在某個(gè)類的頭文件中使用向前聲明來(lái)提及別的類,并在實(shí)現(xiàn)文件中引入那些類的頭文件。這樣做可以盡量降低類之間的耦合(coupling)。
2.有時(shí)無(wú)法使用向前聲明,比如要聲明某個(gè)類遵循一項(xiàng)協(xié)議。這種情況下,盡量把"該類遵循某協(xié)議"的這條聲明移至"class-continuation分類"中。如果不行的話,就把協(xié)議單獨(dú)放在一個(gè)頭文件中,然后將其引入。
<h4>第3條:多用字面量語(yǔ)法,少用與之等價(jià)的方法</h4>
要點(diǎn):
1.應(yīng)該使用字面量語(yǔ)法來(lái)創(chuàng)建字符串、數(shù)值、數(shù)組、字典。與創(chuàng)建此類對(duì)象的常規(guī)方法相比,這么做更加簡(jiǎn)明扼要。
2.應(yīng)該通過(guò)取下標(biāo)操作來(lái)訪問(wèn)數(shù)組下標(biāo)或字典中的鍵所對(duì)應(yīng)的元素。
3.用字面量語(yǔ)法創(chuàng)建數(shù)組或字典時(shí),若值中有nil,則會(huì)拋出異常。因此,務(wù)必確保值里不含nil。
<h4>第4條:多用類型常量,少用#define預(yù)處理指令</h4>
預(yù)處理指令 #define ANIMATION_DURATION 0.3
缺點(diǎn):預(yù)處理過(guò)程會(huì)把碰到的所有ANIMATION_DURATION一律替換為0.3,這樣的話,假設(shè)此指令聲明在某個(gè)頭文件中,那么所有引入了這個(gè)頭文件的代碼,其ANIMATION_DURATION都會(huì)被替換。
若不打算公開(kāi)某個(gè)常量,則應(yīng)將其定義在使用該常量的實(shí)現(xiàn)文件中
static const NSTimeInterval kAnimationDuration = 0.3
優(yōu)點(diǎn):清楚的描述了常量的含義。由此可知該常量類型為NSTimeInterval,這有助于為其編寫開(kāi)發(fā)文檔。如果要定義許多常量,那么這種方式能令稍后閱讀代碼的人更容易理解其意圖。
還要注意常量名稱。常用的命名法是:若常量局限于某“編譯單元”(translation unit,也就是“實(shí)現(xiàn)文件”,implementation file)之內(nèi),則在前面加字母k;若常量在類之外可見(jiàn),則通常以類名為前綴。
有時(shí)候需要對(duì)外公開(kāi)某個(gè)常量。比方說(shuō),你可能要在類代碼中調(diào)用NSNotificationCenter以通知他人。用一個(gè)對(duì)象來(lái)派發(fā)通知,令其他欲接收通知的對(duì)象向該對(duì)象注冊(cè),這樣就能實(shí)現(xiàn)此功能了。派發(fā)通知時(shí),需要使用字符床來(lái)表示此項(xiàng)通知的名稱,而這個(gè)名字就可以聲明為一個(gè)外界的常值變量。這樣的話,注冊(cè)者無(wú)需知道實(shí)際字符串值,只需以常值變量來(lái)注冊(cè)自己想要接收的通知即可。應(yīng)該這樣來(lái)定義:
// In the header file
extern NSString *const EOCStringConstant;
// In the implementation file
NSString *const EOCStringConstant = @"VALUE";
這個(gè)常量在頭文件中“聲明”,且在實(shí)現(xiàn)文件中“定義”。注意const修飾符在常量類型中的位置。所以在本例中,EOCStringConstant就是“一個(gè)常量,而這個(gè)常量是指針,指向NSString對(duì)象”。這與需求相符:我們不希望有人改變此指針常量,使其指向另一個(gè)NSString對(duì)象。
其他類型的常量也是如此。假如要把前例中EOCAnimatedView類里的動(dòng)畫播放時(shí)長(zhǎng)對(duì)外公布,那么可以這樣聲明:
// EOCAnimatedView.h
extern const NSTimeInterval EOCAnimatedViewAnimationDuration;
// EOCAnimatedView.m
const NSTimeInterval EOCAnimatedViewAnimationDuration = 0.3;
這樣定義常量要優(yōu)于使用#define預(yù)處理指令,因?yàn)榫幾g器會(huì)確保常量值不變。一旦在EOCAnimatedView.m中定義好,即可隨處使用。而采用預(yù)處理指令所定義的常量可能會(huì)無(wú)意中遭人修改,從而導(dǎo)致應(yīng)用程序各個(gè)部分所使用的值互不相同。
總之,勿食用預(yù)處理指令定義常量,而應(yīng)該借助編譯器來(lái)確保常量正確,比方說(shuō)可以在實(shí)現(xiàn)文件中用static const 來(lái)聲明常量,也可以聲明一些全局常量。
要點(diǎn):
1.不要用預(yù)處理指令定義常量。這樣定義出來(lái)的常量不含類型信息,編譯器只是會(huì)在編譯前據(jù)此執(zhí)行查找與替換操作,即使有人重新定義了常量值,編譯器也不會(huì)產(chǎn)生警告信息,這將導(dǎo)致應(yīng)用程序中的常量值不一致。
2.在實(shí)現(xiàn)文件中使用static const來(lái)定義“只在編譯單元內(nèi)可見(jiàn)的常量”(translation-unit-specific constant)。由于此類常量不在全局符號(hào)表中,所以無(wú)須為其名稱加前綴。
3.在頭文件中使用extern來(lái)聲明全局常量,并在相關(guān)實(shí)現(xiàn)文件中定義其值。這種常量要出現(xiàn)在全局符號(hào)表中,所以其名稱應(yīng)加以區(qū)隔,通常用與之相關(guān)的類名做前綴。
<h4>第5條:用枚舉表示狀態(tài)、選項(xiàng)、狀態(tài)碼</h4>
一個(gè)字節(jié)含8個(gè)二進(jìn)制位,所以至多能表示可取256種(2的8次方)枚舉(編號(hào)為0~255)的枚舉變量。
要點(diǎn):
1.應(yīng)該用枚舉來(lái)表示狀態(tài)機(jī)的狀態(tài)、傳遞給方法的選項(xiàng)以及狀態(tài)碼等值,給這些值起個(gè)易懂的名字。
2.如果把傳遞給某個(gè)方法的選項(xiàng)表示為枚舉類型,而多個(gè)選項(xiàng)又可同時(shí)使用,那么就將各選項(xiàng)值定義為2的冪,以便通過(guò)按位或操作將其組合起來(lái)。
3.用NS_ENUM與NS_OPTIONS宏來(lái)定義枚舉類型,并指明其底層數(shù)據(jù)類型。這樣做可以確保枚舉是用開(kāi)發(fā)者所選的底層數(shù)據(jù)類型實(shí)現(xiàn)出來(lái)的,而不是采用編譯器所選的類型。
4.在處理枚舉類型的switch語(yǔ)句中不要實(shí)現(xiàn)defauly分支。這樣的話,加入新枚舉之后,編譯器就會(huì)提示開(kāi)發(fā)者:switch語(yǔ)句并未處理所有枚舉。
<h3>第2章 對(duì)象、消息、運(yùn)行期</h3>
<h4>第6條:理解“屬性”這一概念</h4>
<h4>第7條:在對(duì)象內(nèi)部盡量直接訪問(wèn)實(shí)例變量</h4>
<h4>第8條:理解“對(duì)象等同性”這一概念</h4>
<h4>第9條:以“類族模式”隱藏實(shí)現(xiàn)細(xì)節(jié)</h4>
<h4>第10條:在既有類中使用關(guān)聯(lián)對(duì)象存放自定義數(shù)據(jù)</h4>
<h4>第11條:理解objc_msgSend的作用</h4>
<h4>第12條:理解消息轉(zhuǎn)發(fā)機(jī)制</h4>
<h4>第13條:用“方法調(diào)配技術(shù)”調(diào)試“黑盒方法”</h4>
<h4>第14條:理解“類對(duì)象”的用意</h4>
<h3>第3章 接口與API設(shè)計(jì)</h3>
<h4>第15條:用前綴避免命名空間沖突</h4>
<h4>第16條:提供“全能初始化方法”</h4>
<h4>第17條:實(shí)現(xiàn)description方法</h4>
<h4>第18條:盡量使用不可變對(duì)象</h4>
<h4>第19條:使用清晰而協(xié)調(diào)的命名方式</h4>
<h4>第20條:為私有方法名加前綴</h4>
<h4>第21條:理解OC錯(cuò)誤模型</h4>
<h4>第22條:理解NSCopying協(xié)議</h4>
<h3>第4章 協(xié)議與分類</h3>
<h4>第23條:通過(guò)委托與數(shù)據(jù)源協(xié)議進(jìn)行對(duì)象間通信</h4>
<h4>第24條:將類的實(shí)現(xiàn)代碼分散到便于管理的數(shù)個(gè)分類之中</h4>
<h4>第25條:總是為第三方類的分類名稱加前綴</h4>
<h4>第26條:勿在分類中生名屬性</h4>
<h4>第27條:使用“class-continuation分類”隱藏實(shí)現(xiàn)細(xì)節(jié)</h4>
<h4>第28條:通過(guò)協(xié)議提供匿名對(duì)象</h4>
<h3>第5章 內(nèi)存管理</h3>
<h4>第29條:理解引用計(jì)數(shù)</h4>
<h4>第30條:以ARC簡(jiǎn)化引用計(jì)數(shù)</h4>
<h4>第31條:在dealloc方法中只釋放引用并解除監(jiān)聽(tīng)</h4>
<h4>第32條:編寫“異常安全代碼”時(shí)留意內(nèi)存管理問(wèn)題</h4>
<h4>第33條:以弱引用避免保留環(huán)</h4>
<h4>第34條:以“自動(dòng)釋放池塊”降低內(nèi)存峰值</h4>
<h4>第35條:用“僵尸對(duì)象”調(diào)試內(nèi)存管理問(wèn)題</h4>
<h4>第36條:不要使用retainCount</h4>
<h3>第6章 塊與大中樞派發(fā)</h3>
<h4>第37條:理解 "塊"這一概念</h4>
<h4>第38條:為常用的塊類型創(chuàng)建tyoedef</h4>
<h4>第39條:用handler來(lái)降低代碼分散程度</h4>
<h4>第40條:用塊引用其所屬對(duì)象時(shí)不要出現(xiàn)保留環(huán)</h4>
<h4>第41條:多用派發(fā)隊(duì)列,少用同步鎖</h4>
<h4>第42條:多用GCD,少用performSelector系列方法</h4>
<h4>第43條:掌握GCD及操作隊(duì)列的使用時(shí)機(jī)</h4>
<h4>第44條:通過(guò)Dispatch Group機(jī)制,根據(jù)系統(tǒng)資源狀況來(lái)執(zhí)行任務(wù)</h4>
<h4>第45條:使用dispatch_once來(lái)執(zhí)行只需要運(yùn)行一次的線程安全代碼</h4>
<h4>第46條:不要使用 dispatch_get_current_queue</h4>
<h3>第7章 系統(tǒng)框架</h3>
<h4>第47條:熟悉系統(tǒng)框架</h4>
<h4>第48條:多用塊枚舉,少用for循環(huán)</h4>
<h4>第49條:對(duì)自定義其內(nèi)存管理語(yǔ)義的collection使用無(wú)縫橋接</h4>
<h4>第50條:構(gòu)建緩存時(shí)選用NSCache而非NSDictionary</h4>
<h4>第51條:精簡(jiǎn)initialize與load的實(shí)現(xiàn)代碼</h4>
<h4>第52條:別忘了NSTimer會(huì)保留其目標(biāo)對(duì)象</h4>