Effective Objective-C在每一個(gè)Item之后的Things to remember的翻譯,以及一些重要的知識點(diǎn)筆記, 這本書講述了很多關(guān)于Objc的語言特性, 只可惜今后Swift要替代OC了, 發(fā)上來算是紀(jì)念吧.
Item 1:
1.OC是C的超集,增加了面向?qū)ο蟮奶匦?OC用動態(tài)綁定來使用消息傳遞機(jī)制,這意味著一個(gè)對象的類型是在運(yùn)行時(shí)確定的. 一個(gè)消息傳遞所執(zhí)行的代碼在運(yùn)行時(shí)確定而不是編譯時(shí).
2.理解C的原理有助于編寫高效的OC代碼,值得一提的是你需要理解內(nèi)存模型和指針.
Item2:
- 在盡可能深的節(jié)點(diǎn)中導(dǎo)入頭文件, 這通常意味著傳遞聲明類的頭文件和其實(shí)現(xiàn)文件導(dǎo)入的頭文件.這樣做可以極可能避免連接2個(gè)類.
- 有時(shí)候不可能傳遞聲明, 例如聲明一個(gè)協(xié)議. 在這種情況中, 應(yīng)該盡可能考慮把協(xié)議的聲明移到類的category中. 相反地, 導(dǎo)入一個(gè)只有協(xié)議定義的頭文件.
Item3:
- 使用標(biāo)記語法來創(chuàng)建字符串,數(shù)字對象,數(shù)組和字典. 這樣比使用常規(guī)的對象構(gòu)造方法要更簡單明了.
- 使用下標(biāo)方法來訪問數(shù)組或字典對象.
- 使用標(biāo)記語法插入nil對象會拋出異常,因此,時(shí)刻確保插入值不為nil
Item4:
- 避免預(yù)處理器定義(#define). 因?yàn)樗鼈儾话魏晤愋托畔⒉⑶覂H僅是在編譯前做簡單替換. 它們可能被重新定義而沒有任何警告(目前是有的, 可能以前的編譯器版本不支持), 從而在應(yīng)用程序中產(chǎn)生一個(gè)不一樣的值.
- 特定的編譯單元常量在類實(shí)現(xiàn)文件(.m)中用static const來定義. 這些常量不會暴露在全局符號表中, 所以它們的名字不需要在命名空間中.
- 在頭文件中聲明全局常量, 在實(shí)現(xiàn)文件中定義它們. 這些常量將會出現(xiàn)在符號表中, 所以它們的名字將會在命名空間中, 通常為它們加上相對應(yīng)類名的前綴.
Item5:
- 使用枚舉來給狀態(tài)或者狀態(tài)機(jī)命名, 或給方法傳遞狀態(tài)值, 或標(biāo)識出錯(cuò)誤碼
- 使用枚舉來定義可以同時(shí)使用多個(gè)的狀態(tài)值, 將它們定義為2的冪, 以使位的或運(yùn)算來整合它們
- 使用宏NS_ENUM或NS_OPTIONS來定義有顯式類型的枚舉. 這樣做可以保證是自己選擇的類型而不是編譯器選的類型.
- 使用枚舉類型就不要在switch語句中實(shí)現(xiàn)default case. 這將有助于你增加枚舉類型, 因?yàn)榫幾g器會警告你沒有處理所有選項(xiàng)值
Item6:
- @property語法提供了對象數(shù)據(jù)的封裝形式
- 使用屬性來為數(shù)據(jù)存儲提供正確的語義
- 確保@property后面的屬性都已設(shè)置好
- 在iOS上使用 nonatomic, 因?yàn)槿绻褂胊tomic的話會極度地影響性能(編譯器會為其加鎖)
Item7:
直接訪問成員變量和用點(diǎn)語法訪問的區(qū)別:
a. 直接訪問會更快
b. 屬性為copy的變量,直接訪問不會copy, 僅僅是retain一個(gè)對象
c. KVO在直接訪問時(shí)不會被觸發(fā)
d. 通過屬性訪問變量在調(diào)試時(shí)會更容易發(fā)現(xiàn)問題, 因?yàn)槟憧梢栽趃etter和setter函數(shù)中加斷點(diǎn)
- 通過直接訪問來讀, 通過點(diǎn)語法來寫.[在init方法中,要一直使用直接訪問]
- 在init方法和dealloc方法中, 變量的讀寫均用直接訪問
- 有時(shí)候需要數(shù)據(jù)延遲初始化, 就需要通過點(diǎn)語法訪問數(shù)據(jù)
Item8:
- 如果需要比較對象相等就實(shí)現(xiàn)isEqual和hash方法
- 相等的對象一定有相同的hash值, 但是有相同hash值的對象不一定要相等
- 對測試相等性而言, 要決定什么是必要的, 而不是直接測試每一項(xiàng)屬性相等
- 編寫hash方法可以很快比較, 但是也可能會造成hash沖突
Item9:
- 類簇模式可以把實(shí)現(xiàn)細(xì)節(jié)隱藏在簡單的公共表象下
- 類簇廣泛應(yīng)用于系統(tǒng)框架
- 繼承類簇的公共抽象類要注意, 如果有文檔, 仔細(xì)閱讀之.
Item10:
- objc associated 提供了一種鏈接2個(gè)對象的方法
- objc associated 定義了一套模擬持有和非持有關(guān)系的內(nèi)存管理語法
- objc associated 最好在萬不得已的情況下使用, 因?yàn)樗麄兂霈F(xiàn)bug很難被發(fā)現(xiàn)
Item11:
- 消息由接收者, 方法名和參數(shù)構(gòu)成, 發(fā)送消息與調(diào)用一個(gè)對象的方法是一個(gè)意思
- 當(dāng)消息需要發(fā)送時(shí),所有的消息都會經(jīng)過動態(tài)消息分配系統(tǒng),在這里找到對應(yīng)實(shí)現(xiàn)并執(zhí)行
Item12:
要點(diǎn):
@dynamic變量意味著,這些變量的getter和setter函數(shù)不會由編譯器生成,而是自己手動完成,常見于coredata.
- 消息轉(zhuǎn)發(fā)是一個(gè)對象無法找到對應(yīng)的方法時(shí)所經(jīng)過的過程
- 將一個(gè)方法在運(yùn)行時(shí)加入一個(gè)類中稱之為動態(tài)方法方案
- 對象可以聲明自己無法處理的函數(shù), 但是其它對象可以處理
- 全部轉(zhuǎn)發(fā)只有在前面所有的方法都沒能找到合適的函數(shù)時(shí)才被觸發(fā)
Item13:
交換2個(gè)方法的實(shí)現(xiàn):
<code>
Method originalMethod = class_getInstanceMethod([NSString class], @selector(lowercaseString));
Method swappedMethod = class_getInstanceMethod([NSString class], @selector(uppercaseString));
method_exchangeImplementations(originalMethod, swappedMethod);
</code>
- 類的方法的實(shí)現(xiàn)是可以在運(yùn)行時(shí)動態(tài)增加或者替換的
- 用一個(gè)方法實(shí)現(xiàn)與另一個(gè)互換的過程稱之為swizzling, 通常是增加一個(gè)方法替換原來的那個(gè)
- 通常在有益于調(diào)試的時(shí)候才在運(yùn)行時(shí)互換方法實(shí)現(xiàn), 不要僅僅因?yàn)槟阆腱偶季瓦@么做
Item14:
檢驗(yàn)一個(gè)對象是不是某個(gè)類的對象可以用: isMemberOfClass:
檢驗(yàn)一個(gè)對象是不是屬于其父類可以用: isKindOfClass:
- 類的層級通過Class對象來建立, 每一個(gè)對象都有一個(gè)指針來指明其類型
- 當(dāng)不知道對象的類型是不是某種類型時(shí), 需要在編譯時(shí)就用審查來檢驗(yàn)之
- 盡可能使用審查而不是直接比較類型對象, 因?yàn)檫@個(gè)對象可能實(shí)現(xiàn)了消息轉(zhuǎn)發(fā)
Item15:
- 選擇一個(gè)適合公司,應(yīng)用,或者兼顧二者的前綴, 并全面使用之
- 如果自己的庫依賴第三方庫,考慮給它加上自己的前綴
Item16:
- 實(shí)現(xiàn)你指定的(designated)init方法, 并在文檔中寫出. 所有其他的init方法都應(yīng)該通過調(diào)用它來實(shí)現(xiàn)
- 如果指定的init方法與父類不同, 確保指定的init方法被重寫了
- 如果子類不想要父類中的designated init方法中, 那就重寫這個(gè)designated init方法, 并拋出異常
Item17:
- 實(shí)現(xiàn)description方法來為對象提供一個(gè)有意義的字符串描述
- 如果對象描述對調(diào)試很有用, 就實(shí)現(xiàn)debugDescription吧
Item18:
- 如果可以的話, 創(chuàng)建不可變的對象
- 如果需要在內(nèi)部修改只讀變量的值, 則在類的匿名category中拓展屬性到讀寫
- 提供方法來使對象持有的集合可變, 而不是直接暴露可變集合的屬性
Item19:
- 遵從OC中已經(jīng)成為標(biāo)準(zhǔn)的命名方法來創(chuàng)建合適的接口
- 確保方法名是足夠清晰的, 不用太考慮精簡的問題, 讓它們從左至右讀起來像一句話
- 避免在方法名中使用類型的簡寫
- 最重要的是, 確保方法名與你自己的代碼或即將集成的代碼風(fēng)格一致
Item20:
- 為私有方法加一個(gè)前綴, 這樣可以很容易與公共方法區(qū)分出來
- 避免為方法加上下劃線前綴, 因?yàn)檫@樣是蘋果保留的前綴
Item21:
- 只有在足以摧毀整個(gè)應(yīng)用的致命錯(cuò)誤下才使用異常
- 對于非致命錯(cuò)誤, 可以提供delegate方法來處理或者在輸出參數(shù)中提供NSError對象
Item22:
- 如果你的對象需要被copy, 就實(shí)現(xiàn)NSCopying協(xié)議
- 如果你的對象有可變和不可變的變量, 實(shí)現(xiàn)NSCopying和NSMutableCopying兩個(gè)協(xié)議
- 決定用深拷貝或淺拷貝時(shí), 如果可以的話, 在一般拷貝中使用淺拷貝
- 如果深拷貝在你的對象里有用, 考慮增加一個(gè)深拷貝方法
Item23:
- 使用Delegate模式來提供接口一個(gè)對象, 使它可以通知其他對象相關(guān)事件的發(fā)生
- 用隱式可選方法定義協(xié)議, 用來定義你的delegate需要支持的接口(感覺就是用@optional就好了)
- 當(dāng)一個(gè)對象需要從另一個(gè)對象獲得數(shù)據(jù)時(shí), 用delegate模式. 這個(gè)做法通常被成為"data source 協(xié)議"
- 如果有必要, 實(shí)現(xiàn)位域結(jié)構(gòu)方法來緩存delegate是否響應(yīng)協(xié)議中的方法. (在需要頻繁調(diào)用isrespondsSelector這個(gè)方法時(shí), 加入一些標(biāo)志位來直接判斷是否實(shí)現(xiàn))
Item24:
- 使用category來分割一個(gè)類, 把方法實(shí)現(xiàn)在不同的片段中, 使其更容易管理
- 創(chuàng)建一個(gè)Private的category來隱藏那些被定義為私有方法的實(shí)現(xiàn)細(xì)節(jié)
Item25:
- 在為不屬于你的類中增加category時(shí), 要給category的名字加上一個(gè)前綴
- 在為不屬于你的類中增加category時(shí), 要給category中的方法名字加上一個(gè)前綴
Item26:
- 所有的封裝數(shù)據(jù)的屬性聲明都要在主接口中定義(主header, 而不是category的header)
- 在category中聲明屬性的訪問方法更好, 除非是一個(gè)匿名category.
Item27:
- 使用匿名category來為類增加實(shí)例變量
- 如果需要在類的內(nèi)部setter訪問一個(gè)在外部聲明為readonly的屬性, 可以在匿名category中再次聲明這個(gè)屬性為readwrite(前面已經(jīng)提過)
- 在匿名category中聲明私有方法的方法原型
- 在匿名category中聲明你需要保持私有的協(xié)議
Item28:
- 協(xié)議可以用來提供某些匿名類型. 這些匿名類型可以簡寫為那些實(shí)現(xiàn)了協(xié)議方法的id類型
- 當(dāng)類型需要隱藏的時(shí)候使用匿名對象
- 當(dāng)類型無關(guān)緊要且對象響應(yīng)某個(gè)特定方法更為重要時(shí)使用匿名對象
注:所謂匿名對象應(yīng)該就是id類型的對象
Item29:
- 引用計(jì)數(shù)的內(nèi)存管理基于一個(gè)增減的計(jì)數(shù)器, 一個(gè)對象被創(chuàng)建出來計(jì)數(shù)器至少是1, 一個(gè)對象的計(jì)數(shù)器為正數(shù)時(shí)說明它是活躍的, 當(dāng)計(jì)數(shù)器為0這個(gè)對象就會被銷毀
- 對象被其它對象引用和釋放貫穿整個(gè)對象生命周期. 引用和釋放會對應(yīng)增加或減少引用計(jì)數(shù).
Item30:
- ARC把開發(fā)者從大多數(shù)內(nèi)存管理的憂慮中解放了出來, 使用ARC可以減少類中的死板代碼
- ARC通過在合適的地方增加retain和release掌握了對象的幾乎整個(gè)生命周期, 變量修飾詞可用來指示內(nèi)存管理語義, 正如之前所說的手動retain和release一樣
- 返回對象的方法名總是需要用來指示內(nèi)存管理語義的. ARC已經(jīng)鞏固了這個(gè)概念并且基本上已經(jīng)不可能不遵從整個(gè)規(guī)則了
- ARC只能處理Objective-C對象. 這也意味著CoreFoundation對象是無法處理的, 并且必須在合適位置調(diào)用CFRetain和CFRelease
Item31:
- dealloc函數(shù)應(yīng)該只能被用作釋放對其它對象的引用和注銷一切需要注銷的東西, 比如KVO和NSNotification的通知
- 如果一個(gè)對象持有了系統(tǒng)資源, 比如文件描述符, 應(yīng)該要有一個(gè)方法來釋放這些資源. 在使用完資源之后, 應(yīng)該要有一個(gè)被成為close的方法來與他人協(xié)定釋放資源.
- dealloc函數(shù)中應(yīng)該避免調(diào)用其它方法, 防止這些方法試圖異步執(zhí)行, 或者在假設(shè)狀態(tài)下一個(gè)對象是正常狀態(tài), 但其實(shí)它已經(jīng)不是了
Item32:
- 當(dāng)捕獲到異常時(shí), 小心確認(rèn)try代碼塊中創(chuàng)建的對象是否需要清除
- 當(dāng)拋出異常時(shí), ARC默認(rèn)不處理對象清理工作. 可以通過增加編譯器標(biāo)志來處理但是這會增加編譯器產(chǎn)出的代碼量和增加runtime負(fù)載
Ite33:
- 可以使用weak引用來避免造成循環(huán)引用
- weak引用有時(shí)會有時(shí)不會自動置空. 自動置空是ARC引入的新特性并且用runtime實(shí)現(xiàn). 自動置空的弱引用是讀取安全的, 因?yàn)樗肋h(yuǎn)不包含一個(gè)已釋放對象的引用
Item34:
- 自動釋放池安排在棧中, 一個(gè)對象發(fā)送了autorelease消息就會被添加到最頂端的釋放池
- 對自動釋放池的合理應(yīng)用可以減少應(yīng)用的內(nèi)存高線
- 現(xiàn)在的自動釋放池使用性能更加優(yōu)良的@autorelease語法
Item35:
- 當(dāng)一個(gè)對象被釋放, 可以選擇成為僵尸對象而不是被真正釋放. 這個(gè)特性可以通過環(huán)境標(biāo)記NSZombieEnabled來開啟
- 一個(gè)對象成為僵尸對象之后, isa指向?qū)ο蟊旧淼腸lass結(jié)構(gòu)體會被修改為特殊的zombie class結(jié)構(gòu)體. 一個(gè)僵尸類可以響應(yīng)所有的消息, 不過只是打印一條指示什么消息被發(fā)送給什么對象之后的信息之后就會退出整個(gè)應(yīng)用.
Item36:
- 對象的引用計(jì)數(shù)可能起來很有用, 但是通常是沒用的, 因?yàn)榻o定時(shí)間點(diǎn)的絕對引用計(jì)數(shù)并不能給出一個(gè)對象聲明周期的完整視圖
- 當(dāng)ARC來到后, 引用計(jì)數(shù)就被舍棄了, 使用它會造成編譯錯(cuò)誤
Item37:
- block是C, C++和OC的語法閉包(代碼塊)
- block可以選擇傳入?yún)?shù)和返回值
- block可以是棧類型,堆類型和全局類型. 一個(gè)棧類型的block可以copy為堆類型的, 這個(gè)時(shí)候它的引用計(jì)數(shù)器就和標(biāo)準(zhǔn)的OC對象一樣.
Item38:
- 使用typedef以使block的使用更加容易
- 永遠(yuǎn)遵從命名規(guī)則來定義新的類型, 這樣就不會與其它類型沖突
- 不需要擔(dān)心為同樣的block簽名定義多個(gè)類型. 你可能想要在使用某個(gè)block類型的地方通過改變block簽名來重構(gòu), 而不是另外一個(gè)block(實(shí)在不好理解, 原文:Don’t be afraid to define multiple types for the same block signature. You may want to refactor one place that uses a certain block type by changing the block signature but not another.)
Item39:
- Handler block在與創(chuàng)建對象后與業(yè)務(wù)內(nèi)聯(lián)上非常有用
- Handler block在與對象直接聯(lián)系這方面比delegation有更多的優(yōu)勢, 在代理里面如果有多個(gè)對象被發(fā)現(xiàn)需要回調(diào)則需要按對象來區(qū)分(如tableview的delegate就要把tableview回調(diào)回來, 這種做法直接把UI和數(shù)據(jù)耦合在了一起)
- 當(dāng)設(shè)計(jì)一個(gè)API要用到Handler block的時(shí)候, 考慮傳入一個(gè)隊(duì)列的參數(shù), 來指定block需要從哪一隊(duì)中出隊(duì)
Item40:
- 小心block的直接或者間接引入對象會對block進(jìn)行retain, 從而造成潛在的循環(huán)引用問題
- 確保retain cycle會在恰當(dāng)?shù)臅r(shí)候被打破, 不要指望把職責(zé)轉(zhuǎn)嫁到使用你API的用戶上
Item41:
- 調(diào)配隊(duì)列(Dispatch queue)可以用作同步語義并且可以作為@synchronized和NSLock對象的簡單替代
- 混合同步和異步的調(diào)配隊(duì)列可以提供與一般鎖相同的同步行為但是不會把調(diào)用線程封閉在異步調(diào)配中
- 并行隊(duì)列和隔離鎖可以用作更高效的同步行為
Item42:
- performSelector方法族可能會在內(nèi)存管理上出現(xiàn)潛在的危險(xiǎn). 如果無法確定哪個(gè)selector會被執(zhí)行, ARC編譯器就不能正確地插入內(nèi)存管理代碼
- performSelector方法族在傳入?yún)?shù)和返回類型上面的限制有很多(最多2個(gè)參數(shù), 返回類型只是id類型, 有一種做法是直接再寫一個(gè)方法, 接受NSArray集合為參數(shù), 在這個(gè)方法中調(diào)用需要傳遞多個(gè)參數(shù)的方法. 話說回來, 使用performSelector與直接調(diào)用的區(qū)別就是存在一定的延時(shí), 即使delay為0的情況下, performSelector也會延遲在下一個(gè)runloop執(zhí)行)
- 允許selector在其它線程執(zhí)行的方法最好還是用GCD調(diào)用block來實(shí)現(xiàn)
Item43:
- 調(diào)配隊(duì)列不是多線程和任務(wù)管理的唯一解決方案
- 操作隊(duì)列(Operation queue)提供了高級的Objective-C API, 它們能做到大多數(shù)普通GCD可以做到的事. 這些隊(duì)列也可以做到很多復(fù)雜的事情, 而不需要像GCD一樣增加額外的代碼
Item44:
- 組調(diào)配(Dispatch group)用來分組一系列的任務(wù). 當(dāng)組任務(wù)執(zhí)行結(jié)束后你可以選擇接受通知
- 組調(diào)配可以通過并行調(diào)配隊(duì)列來執(zhí)行多任務(wù). 在這種情況下, GCD可以在同一時(shí)間基于系統(tǒng)資源來處理多任務(wù)的安排. 自己來實(shí)現(xiàn)就需要寫大量的代碼
Item45:
- 僅僅執(zhí)行一次且線程安全是一個(gè)常有的任務(wù). GCD提供了一個(gè)簡單易用的工具--dispatch_once函數(shù)--來完成這項(xiàng)任務(wù)
- 令牌(token)應(yīng)該被聲明為static或者global, 以使得每次執(zhí)行這一塊代碼時(shí)都是傳入了同一個(gè)token
Item46:
- dispatch_get_current_queue函數(shù)并不總是像你期待那樣執(zhí)行. 它已經(jīng)被棄用應(yīng)該僅用作debug
- 調(diào)配隊(duì)列以分層方式組織, 因此當(dāng)前隊(duì)列不能簡單地用單個(gè)隊(duì)列對象來描述
- 特定隊(duì)列數(shù)據(jù)可以被用來解決尋常的用dispatch_get_current_queue的問題, 這樣可以避免非可重入代碼的死鎖
Item47:
- 許多Framework都是可用的. 最重要的Foundation和CoreFoundation提供了組建應(yīng)用最核心的功能
- Framework為很多普通任務(wù)而生, 比如音視頻處理, 網(wǎng)絡(luò)和數(shù)據(jù)管理
- 記住, 用純C寫的framework對你來說比Objecttive-C寫的framework更重要, 成為一個(gè)好的Objective-C開發(fā)者你需要理解C的核心概念
Item48:
用block來遍歷集合:
[anArray enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop){
// Do something with 'object'
if (shouldStop)
{
stop = YES;
}
}];
有幾點(diǎn)好處:可以同時(shí)得到index和object, 如果不想繼續(xù)遍歷則stop=YES就好. 同時(shí)不需要進(jìn)行一次轉(zhuǎn)換, 如果明確集合中的元素類型可以直接^(NSString *str, NSUIntger idx, BOOL *stop){...} 這樣來轉(zhuǎn)換
同樣可以在dictionary和set中用.
更多選擇:
(void)enumerateObjectsWithOptions: (NSEnumerationOptions)options
usingBlock:(void(^)(id obj, NSUInteger idx, BOOL *stop))block(void)enumerateKeysAndObjectsWithOptions: (NSEnumerationOptions)options
usingBlock:(void(^)(id key, id obj, BOOL *stop))block
- 有四種方法可以實(shí)現(xiàn)集合元素遍歷. for循環(huán)是最基本的, 隨后的是用NSEnumerator遍歷和快速遍歷. 最現(xiàn)代和高端的方法是用block遍歷方法
- block遍歷允許你通過GCD并行實(shí)現(xiàn)遍歷而不需要增加任何代碼. 用其他的方法遍歷并不能輕易做到
- 如果你知道遍歷元素的類型可以更改block簽名來指明它們.
Item49:
- Toll-Free Bridging可以讓你在Foundation框架下的Objective-C對象和CoreFoundation框架下C數(shù)據(jù)結(jié)構(gòu)之間轉(zhuǎn)換
- 降級到使用CoreFoundation來創(chuàng)建集合讓你你使用特定的變種回調(diào)函數(shù)來處理集合的元素. 通過toll-free bridging可以讓你規(guī)避Objective-C集合需要的一些內(nèi)存管理語法
Item50:
- 考慮使用NSCache來替換NSDictionary來緩存數(shù)據(jù). NSCache有良好的裁剪行為,線程安全,并且不會像dictionary那樣復(fù)制key
- 使用數(shù)量限制和負(fù)載限制來操作需要從緩存中裁剪對象的數(shù)量. 但是永遠(yuǎn)不要依賴這些量成為硬限制, 它們僅僅是緩存的一個(gè)指導(dǎo)而已
- 使用NSPurgeableData對象來緩存提供自動清除的數(shù)據(jù)(這些數(shù)據(jù)會在緩存清除中被自動移出)
- 如果緩存使用得當(dāng)會使你的程序響應(yīng)更加快速. 只需要緩存那些重新計(jì)算非常耗時(shí)的數(shù)據(jù), 比如那些需要從網(wǎng)絡(luò)或者磁盤中獲取的數(shù)據(jù)
Item51:
- 類實(shí)現(xiàn)后會調(diào)用load方法. load方法可能會出現(xiàn)在category中, 類的load總是category的load之前. load方法不像其它方法, 它并不會被重寫
- 實(shí)現(xiàn)load和initialize方法必須要非常簡潔, 這有助于保持應(yīng)用的快速響應(yīng)并且減少可能引入的內(nèi)部依賴循環(huán)
- 在initialize方法中設(shè)置不能在編譯期間就設(shè)置好的全局狀態(tài). (原文:Keep initialize methods for setting up global state that cannot be done at compiletime)
Item52:
- NSTimer對象會retain它的目標(biāo)(target), 直到定時(shí)器因被觸發(fā)或者顯式調(diào)用invalidate而失效
- 使用重復(fù)定時(shí)器很容易引入循環(huán)引用(如果定時(shí)器的目標(biāo)retain定時(shí)器). 這在對象視圖中可能會直接或者間接出現(xiàn).
- NSTimer使用block拓展可以打破循環(huán)引用. 在這個(gè)方法成為NSTimer接口之前, 我們可以通過category來實(shí)現(xiàn)之:
- (void)startPolling {
__weak EOCClass *weakSelf = self;
_pollTimer = [NSTimer eoc_scheduledTimerWithTimeInterval:5.0
block:^{
EOCClass *strongSelf = weakSelf; [strongSelf p_doPoll];
}
repeats:YES];
}