《Effective Objective-C 2.0》讀書(shū)筆記

本篇博客作為讀書(shū)筆記,主要記錄和整理閱讀EOC(《Effective Objective-C 2.0 編寫(xiě)高質(zhì)量iOS與OS X代碼的52個(gè)有效方法》)時(shí)的收貨和感悟



1.了解OC語(yǔ)言的起源

了解OC的語(yǔ)言特性(運(yùn)行時(shí)),OC的發(fā)展來(lái)源(C的超集),語(yǔ)法,內(nèi)存管理策略等。

2.在類的頭文件中盡量少引入其他頭文件

在.h中引入其他頭文件,會(huì)大幅度增加編譯所需的時(shí)間,也有可能會(huì)導(dǎo)致循環(huán)引入的問(wèn)題。應(yīng)當(dāng)盡量使用“前向聲明”(@class)的方式來(lái)聲明其他類的存在。 為了避免在.h中引入定義協(xié)議的頭文件,遵守協(xié)議應(yīng)該寫(xiě)在.m中的類擴(kuò)展里,而不是寫(xiě)在.h中

3.多用字面量語(yǔ)法,少用與之等價(jià)的方法

了解和掌握用于快速創(chuàng)建NSNumber、NSArray、NSDictionary的字面量語(yǔ)法:@num,@[],@{};以及相應(yīng)的下標(biāo)運(yùn)算符。需要了解數(shù)組和字典創(chuàng)建時(shí)遇到nil值會(huì)結(jié)束的特性,以及使用字面量語(yǔ)法帶來(lái)的好處。

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

在定義僅類內(nèi)部使用的常量時(shí),應(yīng)該盡量使用static const的方式來(lái)定義。這種定義的會(huì)限制其類型,并且避免其他文件的修改。當(dāng)定義全局變量時(shí),應(yīng)使用在類內(nèi)部定義全局變量,在頭文件中使用extern引用全局常量的做法。

5.用枚舉表示狀態(tài)、選項(xiàng)、狀態(tài)碼

了解為什么用枚舉更好、怎么使用C++11帶來(lái)的新枚舉用法,以及OC中定義的快速創(chuàng)建枚舉宏的用法。了解和掌握NS_ENUM和NS_OPTIONS宏的用法。

6.理解“屬性”這一概念

使用@property語(yǔ)法時(shí),編譯器會(huì)自動(dòng)生成getter方法和setter方法以及成員變量的。掌握@property的關(guān)鍵字:四種類型(原子性、內(nèi)存管理策略、讀寫(xiě)性、讀寫(xiě)方法重命名),以及分別的使用場(chǎng)景和原理。

7.在對(duì)象內(nèi)部盡量直接訪問(wèn)實(shí)例變量

了解通過(guò)屬性訪問(wèn)實(shí)例變量會(huì)觸發(fā)什么(調(diào)用setter或getter方法,觸發(fā)KVO)了解使用屬性來(lái)訪問(wèn)成員變量和直接訪問(wèn)成員變量?jī)烧叩膮^(qū)別與優(yōu)劣:直接訪問(wèn)成員變量效率更快。

8.理解“對(duì)象等同性”這一概念

了解isEqual:這一方法的原理,了解NSString中isEqualToString:這一方法做了什么事情。了解如果需要自定義方法來(lái)判斷兩個(gè)對(duì)象是否相等應(yīng)該怎么做。

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

了解類族的概念,了解如何通過(guò)工廠方法來(lái)創(chuàng)建類族子類對(duì)象。掌握如何通過(guò)工廠模式設(shè)計(jì)工廠方法來(lái)實(shí)例化子類對(duì)象。

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

掌握runtime中的objc_setAssociatedObjectobjc_getAssociatedObject方法的作用和用法。掌握冬天獲取和添加成員變量的方式。

11.理解objc_msgSend的作用

理解和掌握OC中的消息機(jī)制,理解"selector"、"IMP"的含義。了解objc_msgSend方法的意義

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

了解OC運(yùn)行時(shí)機(jī)制,了解當(dāng)消息接收者無(wú)法處理消息時(shí),會(huì)調(diào)用哪些方法。掌握使用resolveInstanceMethod:resolveClassMethod:方法來(lái)動(dòng)態(tài)添加方法、使用forwardingTargetForSelector:方法來(lái)轉(zhuǎn)發(fā)消息、使用forwardInvocation:方法來(lái)處理完整的消息轉(zhuǎn)發(fā)。

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

了解和掌握runtime方法調(diào)用流程,了解"method swizzling"的原理和用法,掌握使用class_getInstanceMethodclass_getClassMethod函數(shù)來(lái)獲取方法實(shí)現(xiàn),使用method_exchangeImplementations函數(shù)來(lái)交換方法實(shí)現(xiàn)。同時(shí)需要了解在使用"method swizzling"時(shí),自定義的方法中如何規(guī)避調(diào)用自身的問(wèn)題。

14.理解“類對(duì)象”的用意

了解OC對(duì)象的實(shí)現(xiàn)方式,了解“類對(duì)象”,“isa指針”,“元類對(duì)象”的概念。掌握isMemberOfClass:方法和isKindOfClass:方法的作用。

15.用前綴避免命名空間沖突

理解編寫(xiě)自己的類時(shí),使用命名前綴。

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

理解和掌握在類的初始化方法中提供一個(gè)被其他所有初始化方法調(diào)用的“全能初始化方法”。其他初始化方法都調(diào)用這個(gè)方法來(lái)創(chuàng)建實(shí)例對(duì)象,在這個(gè)初始化方法中進(jìn)行對(duì)象的具體配置。

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

掌握通過(guò)重寫(xiě)自定義類的description方法來(lái)實(shí)現(xiàn)描述信息的返回。了解使用debugDescription方法在LLDB中進(jìn)行調(diào)試打印。

18.盡量使用不可變對(duì)象

理解定義公開(kāi)屬性時(shí)盡量使用不可變版本的原因,了解在類擴(kuò)展中修改為readwrite以便類內(nèi)部可以修改。了解對(duì)外公開(kāi)的集合屬性的返回方式。

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

了解OC中方法名的命名規(guī)范,了解駝峰法書(shū)寫(xiě)方式,方法名在言簡(jiǎn)意賅的同時(shí)最好能完整敘述方法的功能,并給每個(gè)參數(shù)都加上相應(yīng)的提示。 方法名中不要使用類型名的縮寫(xiě)而是使用類型名的全稱。類名、協(xié)議名要加上對(duì)應(yīng)的前綴。

20.為私有方法名加前綴

為了避免與公有方法混亂,或是無(wú)意中覆蓋了父類中的共有方法,在書(shū)寫(xiě)類的私有方法時(shí)應(yīng)該給方法加上前綴,比如以p_為前綴。不要僅使用一個(gè)單下劃線_作為私有方法的前綴,避免和系統(tǒng)類的私有方法重合。

21.理解Objective-C錯(cuò)誤模型

了解NSException的使用方法和應(yīng)用場(chǎng)景。了解NSError的使用。

22.理解NSCopying協(xié)議

在OC中想要拷貝一個(gè)對(duì)象時(shí),通常使用copy方法。該對(duì)象對(duì)應(yīng)的類需要遵循NSCopying協(xié)議,并實(shí)現(xiàn)協(xié)議中的copyWithZone:方法。如果需要拷貝可變的版本,則需要遵守NSMutableCopying協(xié)議并實(shí)現(xiàn)mutableCopyWithZone:方法。了解深拷貝和淺拷貝的區(qū)別以及實(shí)現(xiàn)方式。

23.通過(guò)委托與數(shù)據(jù)源協(xié)議進(jìn)行對(duì)象間通信

理解OC中代理設(shè)計(jì)模式的實(shí)現(xiàn)思路,掌握delegate和dataSource形式的協(xié)議設(shè)計(jì)。性能優(yōu)化方面,可以將代理是否實(shí)現(xiàn)了代理方法在賦值時(shí)進(jìn)行緩存,可以大大優(yōu)化頻繁調(diào)用代理方法時(shí)的效率。

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

可以將不同模塊的代碼分散到類的分類中,僅把主要的核心代碼保存在主文件中。分類既可以存放在主文件的中,劃分不同模塊保存,也可以創(chuàng)建不同的分類文件進(jìn)行保存。

25.總是為第三方類的分類名稱加前綴

為了避免重名的情況,分類文件名都應(yīng)該盡量加上前綴。為了避免分類中的方法實(shí)現(xiàn)覆蓋了其他分類中的實(shí)現(xiàn)或原實(shí)現(xiàn),應(yīng)該給方法名也加上相應(yīng)的前綴。

26.勿在分類中聲明屬性

由于分類中不會(huì)合成屬性對(duì)應(yīng)的成員變量,因此不應(yīng)該在分類中聲明屬性。雖然可以使用runtime動(dòng)態(tài)添加的方式綁定,但這一并不好,不應(yīng)該在非必須的時(shí)候這樣做。分類中應(yīng)該盡量只用來(lái)擴(kuò)充方法。

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

掌握使用類擴(kuò)展來(lái)給類擴(kuò)充私有實(shí)例變量。如果想要使主接口中聲明為“只讀”的屬性能夠在內(nèi)部修改,應(yīng)該在類擴(kuò)展中將其改寫(xiě)為“可讀寫(xiě)”

28.通過(guò)協(xié)議提供匿名對(duì)象

了解通過(guò)協(xié)議來(lái)隱藏對(duì)象類型細(xì)節(jié)。如果具體類型不重要,重要的是對(duì)象能響應(yīng)的方法,可以使用匿名對(duì)象的方式實(shí)現(xiàn)。

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

了解和掌握OC中進(jìn)行內(nèi)存管理的機(jī)制,了解引用計(jì)數(shù)的概念,以及在MRC環(huán)境下進(jìn)行對(duì)象內(nèi)存管理所需使用到的常用方法(retain,release,autorelease,delloc)。

30.以ARC簡(jiǎn)化引用計(jì)數(shù)

了解ARC的概念,明白編譯器在ARC環(huán)境下做了哪些事情。并且理解循環(huán)引用的概念,了解怎么在ARC模式下怎么避免內(nèi)存泄漏。

31.在delloc方法中只釋放引用并解除監(jiān)聽(tīng)

在delloc方法中只應(yīng)該進(jìn)行釋放對(duì)象引用(尤其是CF中的對(duì)象),以及移除觀察者、通知監(jiān)聽(tīng)的操作。如果有大量占用內(nèi)存的對(duì)象需要提前釋放,應(yīng)該在自定義的方法中釋放。

32.編寫(xiě)“異常安全代碼”時(shí)留意內(nèi)存管理問(wèn)題

由于在ARC環(huán)境下,捕獲異常時(shí)沒(méi)辦法釋放對(duì)象引用,所以需要開(kāi)啟編譯器的-fobjc-arc-exceptions標(biāo)志來(lái)避免內(nèi)存泄露。不過(guò)在非必要的時(shí)候不要開(kāi)啟,避免對(duì)性能的影響。

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

當(dāng)有循環(huán)引用時(shí),使用weak指針(__weak修飾符)來(lái)修飾對(duì)象,避免循環(huán)引用導(dǎo)致的內(nèi)存泄漏。

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

在MRC環(huán)境下,可以通過(guò)手動(dòng)創(chuàng)建自動(dòng)釋放池的方式來(lái)提前釋放內(nèi)存。

35.用“僵尸對(duì)象”調(diào)試內(nèi)存管理問(wèn)題

通過(guò)在編譯器scheme中編輯中打開(kāi)僵尸對(duì)象的監(jiān)測(cè)來(lái)解決懸垂指針的問(wèn)題。了解僵尸對(duì)象的概念和行成過(guò)程。

36.不要使用retainCount

即使在MRC模式下,retainCount方法返回的引用計(jì)數(shù)也并不可靠,不要使用該方法進(jìn)行對(duì)象內(nèi)存管理的判斷。

37.理解“塊”這一概念

了解block的基本概念和使用場(chǎng)景,了解自定義block類型的方式。了解block對(duì)象的內(nèi)存管理情形。

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

掌握使用typedef給block起別名,把類中常用的block類型定義為自定義的數(shù)據(jù)類型。

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

掌握使用block回調(diào)的方式進(jìn)行傳值,使用completionHandler來(lái)處理完成回調(diào),或者以兩個(gè)block參數(shù)分別作為成功和失敗的回調(diào)。這樣做比使用delegate的方式更加便捷,并且具有可讀性。

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

由于block會(huì)自動(dòng)捕獲其中使用到的對(duì)象,對(duì)其進(jìn)行一次引用,所以在使用block時(shí)需要注意循環(huán)引用的情況??梢酝ㄟ^(guò)手動(dòng)解除引用的方式解決,也可以通過(guò)將被捕獲的對(duì)象用__weak修飾符修飾的方式解決。

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

當(dāng)需要自己編寫(xiě)帶有線程安全機(jī)制的代碼時(shí),可以考慮使用GCD的同步異步函數(shù)方式來(lái)實(shí)現(xiàn)。

42.多用GCD,少用performSelector系列方法

performSelector方法由于存在內(nèi)存管理的缺陷,以及參數(shù)和返回值類型限制等問(wèn)題,不建議使用。最好使用GCD的方法來(lái)實(shí)現(xiàn)方法調(diào)用和線程通信。

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

了解和掌握NSOperation的使用,在實(shí)現(xiàn)多線程時(shí)也可以考慮使用。當(dāng)需要處理任務(wù)取消、添加依賴、鍵值觀察、指定任務(wù)優(yōu)先級(jí)這些gcd無(wú)法實(shí)現(xiàn)的功能時(shí)應(yīng)該用NSOperation來(lái)解決。

44.通過(guò)Dispatch Group機(jī)制,根據(jù)系統(tǒng)資源狀況來(lái)執(zhí)行任務(wù)

當(dāng)需要等待某個(gè)或某些任務(wù)執(zhí)行完畢時(shí),可以通過(guò)將任務(wù)添加到一個(gè)隊(duì)列組的方式實(shí)現(xiàn)。使用dispatch_group_notify方法來(lái)實(shí)現(xiàn)當(dāng)隊(duì)列中任務(wù)全部完成時(shí)執(zhí)行某一代碼塊。

45.使用dispatch_once來(lái)執(zhí)行只需運(yùn)行一次的線程安全代碼

當(dāng)需要編寫(xiě)在整個(gè)程序運(yùn)行的生命周期中只會(huì)運(yùn)行一次的代碼,可以使用gcd的dispatch_once函數(shù)來(lái)實(shí)現(xiàn)。單例設(shè)計(jì)模式中推薦使用這種方式而不是線程鎖

46.不要使用dispatch_get_current_queue

dispatch_get_current_queue函數(shù)已經(jīng)廢棄,而且該函數(shù)返回的隊(duì)列很可能與開(kāi)發(fā)者預(yù)期的不同,因此使用的時(shí)候容易出現(xiàn)問(wèn)題。應(yīng)使用隊(duì)列特定數(shù)據(jù)的方式來(lái)解決。

47.熟悉系統(tǒng)框架

熟練掌握Foundation框架和CoreFoundation框架的主要功能,熟悉常用的音頻視頻處理、網(wǎng)絡(luò)通信、數(shù)據(jù)管理等系統(tǒng)框架,避免在開(kāi)發(fā)中自己去實(shí)現(xiàn)一些系統(tǒng)已經(jīng)實(shí)現(xiàn)好了的功能。

48.多用塊枚舉,少用for循環(huán)

掌握幾種遍歷集合的方式,掌握使用塊循環(huán)enumerateObjectsUsingBlock:方法來(lái)實(shí)現(xiàn)遍歷。

49.對(duì)自定義其內(nèi)存管理語(yǔ)義的collection使用無(wú)縫橋接

了解和掌握Foundation對(duì)象和CoreFoundation數(shù)據(jù)結(jié)構(gòu)之間轉(zhuǎn)換的方式。

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

在進(jìn)行數(shù)據(jù)持久化緩存時(shí),應(yīng)該優(yōu)先使用NSCache類來(lái)實(shí)現(xiàn)。NSCache相比NSDictionary具有自動(dòng)刪減、線程安全、不拷貝鍵的優(yōu)勢(shì)。

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

load方法在代碼被加載到代碼區(qū)的時(shí)候調(diào)用,盡量不要在load方法中做復(fù)雜的工作,避免影響應(yīng)用程序的啟動(dòng)速度。load方法和initialize方法中都應(yīng)該避免對(duì)其他類的調(diào)用,避免加載或初始化時(shí)機(jī)差異導(dǎo)致的問(wèn)題。未實(shí)現(xiàn)load方法的子類,即使父類實(shí)現(xiàn)了,也不會(huì)調(diào)用;未實(shí)現(xiàn)initialize方法的子類,會(huì)調(diào)用其父類的方法。

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

當(dāng)創(chuàng)建一個(gè)Timer對(duì)象時(shí),timer會(huì)保留其引用到的target對(duì)象,如果timer的模式是重復(fù)執(zhí)行的,那么會(huì)有很大的可能產(chǎn)生循環(huán)引用。應(yīng)該使用block的方式創(chuàng)建,或手動(dòng)invalidate timer來(lái)避免內(nèi)存泄露的問(wèn)題.


《Effective Objective-C 2.0》全書(shū)的內(nèi)容到這里就介紹完了,這本書(shū)非常全面的介紹了iOS開(kāi)發(fā)中比較常遇到的問(wèn)題或者需要規(guī)避的坑,還是非常有幫助的,有條件的讀者建議自己買一本或借一本讀一下,肯定會(huì)有不少收獲!


之后會(huì)給大家?guī)?lái)一篇由iOS開(kāi)發(fā)大牛唐巧撰寫(xiě)的《iOS開(kāi)發(fā)進(jìn)階》的讀書(shū)筆記,希望能給大家?guī)?lái)一些收獲!敬請(qǐng)期待!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容