1.OC消息結構語言,其運行時所應執行的代碼由運行環境決定; 動態性語言。 OC語言的對象所佔的內存老是分配在堆空間,毫不會分配在棧空間。 指針的大小:32位4字節,64位機8字節。數組
2.在類的頭文件裏儘可能少引用其餘頭文件。 可使用@class向前聲明類的方法。 這能夠相應的減小編譯時間。 注意:類遵循某個協議,就必須引用完整,不能使用向前聲明方法。 (所以也就出現了:1.要麼將協議移到class-continuation裏;2.若是不行,就把協議單獨放到一個頭文件裏,而後引入。)緩存
3.多使用字面量語法,少使用與之等價的方法 NSArray *array = [@"name", @"title"]; 而不要使用 NSArray *array = [NSArray arrayWithObjects:@"name",@"title",nil]; NSDictionary 同理。 這樣子建立,就能夠經過去下標的方式取對應的元素了。方便。安全
4.多用類型常量,少用#define 宏預處理 能夠參考官方通知名稱的寫法。網絡
5.用枚舉表示狀態、選項、狀態碼 首先枚舉名字直接易懂。 枚舉分 NS_ENUM 和 NS_OPTIONS。 具體使用:須要以按位或操做組合的都用NS_OPTIONS,不用互相組合的用NS_ENUM。 另外枚舉使用switch的時候,不要加default。 這樣子,新增枚舉值,編譯器就會給出警告信息。框架
6.屬性 @property 自動生成set get方法。 ABI: Application Binary Interface 應用程序二進制接口。 assign: 只會執行「純量類型(CGFloat, NSInteger)」的簡單賦值操做。 strong: 定義一種擁有關係。 先保留新值,並釋放舊值,而後再將新值設置上去。 copy:設置方法並不保留新值,而是將其拷貝。 weak:定義了一種「非擁有關係」。 設置方法既不保留新值,也不釋放舊值。 對象摧毀時,屬性也會清空nil。 unsafe_unretained: 和assign 相同,它適用於對象類型。 也是「非擁有關係」。 可是對象摧毀,不會置空nil。 這和weak的區別。函數
atomic:使用同步鎖開銷較大,會帶來嚴重的性能問題。性能
7.在對象內部儘可能直接訪問實例變量 讀取實例變量的時候才用直接訪問的形式,而在設置實例變量的時候經過屬性來作。 懶加載必須經過「獲取方法」來訪問屬性。atom
8.對象等同性 ==操做符比較的兩個對象的指針自己,不是其所指的對象。 isEqual:方法判斷兩個對象的等同性。 若是isEqual判斷兩個對象相等,那麼其hash方法也必返回同一個值。反之,不必定。spa
9.以類族的方式隱藏實現細節 參考UIButton的定義方法。 只需傳入Button類型,不用管內部具體實現。系統框架方法裏很是常見。線程
10.既有類中使用關聯對象存放自定義數據 objc_setAssociatedObject()方法。 只有其餘方法不行時才使用,由於這個方法一般會引入難於查找的bug。
11.理解objc_msgSend方法 在底層,全部的方法都是普通的C語言函數,然而對象收到消息以後,究竟該調用哪一個方法則徹底在運行期決定,甚至能夠在程序運行時改變,這就是OC是一門真正的動態性語言。
12.理解消息轉發機制 第一階段:動態方法解析 +(BOOL) resloveInstanceMethod:(SEL)selector 在此方法裏,你能夠插入一個已經實現的方法。 第二階段:完整的消息轉發機制。網上有一個經典的處理流程圖。 越日後處理的代價越大。
13.方法調配技術調試黑盒方法 method swizzling 方法交換。 這種方法不要亂用,不然出bug很難定位。
14.理解類對象的用意 類對象底層是Struct。 這個要掌握看看。 isa、 super_class、 *name、 version、info、instance_size.等等 isMemberOfClass:判斷對象是否爲某個特定類的實例。 isKindOfClass:對象是否爲某個類或其派生類的實例。
15.加前綴避免命名空間衝突 注意:兩字母大寫前綴Apple爸爸宣稱它保留使用的權利,因此咱們最好使用三字母前綴。
16.提供全能初始化方法 全部對象均要初始化。 若是有多種初始化方法,搞一個全能初始化方法,全部初始化方法都調用它。
17.實現description方法 實現description方法,返回一個更有意義的字符串,用於描述該實例。 若想在調試的時候打印更詳盡的對象信息,應該實現debugDescription方法。
18.儘可能使用不可變對象 readonly 若是這個屬性不想外部改變,就用readonly修飾。 若是外部只想調用某個屬性, 能夠在.h文件中修飾readonly,在.m文件裏修飾爲readwrite。
19.使用清晰而協調的命名方式 方法與變量使用駝峯式大小寫命名方式。 方法命名不要吝嗇使用長的方法名,定義的方法應該直接就能夠看出其語義做用。
20.爲私有方法加前綴 這樣能夠很好的共有方法區別開來。 不過注意:一個下劃線方式(_)不要使用,Apple爸爸說這個要給它預留的。
21.Objective-C的錯誤類型 OC裏的異常,只應該用於及其嚴重的錯誤(fatal error),不能夠用其處理通常錯誤類型。 在錯誤不那麼嚴重的狀況下,可使用代理方式來處理、傳遞錯誤。 當NSError當參數傳遞錯誤時,實際上傳遞的是一個指針。 (NSError )error。 指針自己又指向一個指針,那個指針指向NSError對象。 在ARC下NSError 轉化爲 NSError*__autoreleasing* 的。 即:指針所指的對象會在方法執行完畢後自動釋放。 這個隊形也必須自動釋放,由於處理錯誤的方法對象不能保證能夠把方法中建立的NSError釋放掉,因此必須autorelease。
22.NSCopying 協議 若是想讓某個類支持copy操做,那就要實現NSCopying協議,該協議只有一個方法:
23.經過委託與數據源協議進行對象間的通訊Delegate 委託模式爲對象提供了一套接口。
24.將類的實現代碼分散到便於管理的數個分類之中category 利用分類機制把類的實現劃分爲易於管理的小模塊。 私用方法納入private分類中
25.老是要爲第三方分類添加名稱前綴 不加前綴容易覆蓋原來的方法,一旦覆蓋,以最後加載的一個分類爲準。
26.不要在分類中聲明屬性 雖說能夠經過objc_setAssociatedObject: 方法添加,可是不推薦。分類目標在於擴展類的功能,而非封裝數據。 把封裝數據所用的所有屬性都定義在主接口裏。
27.使用class-continuation分類 隱藏實現細節 將就在本類使用的屬性寫在class-continuation分類。若是隻需外部訪問的屬性,能夠在.h裏聲明成readonly。 .m文件裏的@interface class {} @end
28.經過協議提供匿名對象 Id. ID類型, 至關於匿名。。
29.理解引用計數 保留計數不能說必定是某個值,應該說你執行的操做,是遞增了仍是遞減了該計數。 XXX = nil; 懸掛指針,防止出現指向無效對象的指針,從而形成可能的crash。 autorelease:釋放操做在下一次事件循環時纔回收。 所以它能夠延長對象的生命週期,使其跨越方法邊界依然能夠存活一段時間。 ARC下:不能夠調用:retain release autorelease dealloc 方法
30.以ARC簡化引用計數 內存泄漏:沒有正確釋放已經再也不使用的內存。 非OC對象,好比CoreFoundation中的對象,或是有malloc()分配在堆中的內存,要手動清理。 CFRelease。
31.在dealloc方法中只釋放引用並解除監聽 通知一旦發給了已經回收了的對象,必然crash。 dealloc方法裏面不該該調用任何其餘方法,由於此時對象已經接近尾聲了。
32.編寫「處理異常代碼」時要注意內存管理問題 在OC 中應該程序必須因異常情況而終止時才應該拋出異常。fatal error(參見第21條)。 程序即將終止,內存能夠不處理。 可是若是本身非要處理異常,必定要注意try 方法內清理好對象內存。 -fobjc-arc-exceptions 在ARC下大能夠捕獲異常標誌。 可是這樣運行效率會變低。
33.用弱引用避免保留環 weak 與 unsafe_unretained 做用徹底一致,然而weak修飾的屬性,只要系統回收了,會自動設爲nil。
34.用autoreleasepool 下降內存峯值 GCD、數組block遍歷等線程都默認建立了自動釋放池。每次執行「事件循環」時,就會將其清空。 autoreleasepool 能夠多層嵌套, 它的做用範圍就在其大括號{}之間。。 若是內存峯值不是很大,儘可能不要額外創建自動釋放池。
35.用「殭屍對象」調試內存管理問題 Zoombie Objects 向已經回收的對象發送消息是不安全的。 不是必crash的。 這取決於:對象所佔的內存有沒有被其它內容所複寫。。 系統會修改對象的ISA指針,令其指向特殊的殭屍類,從而使其變成殭屍對象。NSZombie 也是一個根類,和NSObject同樣。 殭屍類能夠響應任何選擇子,響應方式:打印一套消息內容及接收者信息,並終止程序。
36.不要使用retainCount 由於retainCount返回的是某個節點的計數值,並不能考慮到後續系統可能會清掉、釋放操做。 因此它是不能準確反映計數值得。
37.理解塊這一律念 Block:帶有自動變量(局部變量)的匿名函數。 查看Block源碼,它也有一個isa指針,因此實質上block就是OC對象。 Block根據存儲區域分爲三種: _NSConcreteStackBlock _NSConcreteMallocBlock _NSConcreteGlobalBlock 棧、堆、程序數據(靜態)Block
38.一般用typedef建立塊 方便寫,也方便閱讀。 block表達式: ^返回值類型 參數列表 表達式
39.使用handler塊下降代碼分散程度 通常獲取網絡數據用塊處理很方便,由於在塊定義範圍內能夠直接獲取塊內的全部變量。
40.使用塊引用其所屬對象時不要出現保留環 41.多用派發隊列,少用同步鎖 @synchronized(self){ //會下降代碼效率,公用不用一個鎖的同步塊,都必須按順序執行 } 使用同步隊列及柵欄塊,能夠令同步行爲更加高效。
42.多用GCD,少用performSelector系列方法 performSelector系列方法在內存管理方面容易有疏失。它沒法肯定將要執行的選擇子具體是什麼,由於ARC編譯器也沒法適當的插入內存管理方法。
43.掌握GCD及操做隊列的使用時機 在執行後臺任務時,GCD並不必定是最佳方式。 還有一個NSOperationQueue。 SD庫就是用的這方式。 它的好處: 能夠取消某個操做, 可是已經啓動的不能取消。 能夠指定操做間的依賴關係。能夠指定優先級。能夠經過兼職觀測機制監控NSOperation對象屬性。
44.dispatch_group 注意一對函數。 dispatch_group_enter dispatch_group_leave 必然成對出現。 這個主要用於函數回調完了 在執行notify方法。
45.使用dispatch_once來執行只需運行一次的線程安全代碼 dispatch_once簡化代碼並能完全保證線程安全。 更高效
46.不要使用dispatch_get_current_queue 此函數已經廢除,最多在調試的時候使用
47.熟悉系統框架 框架:將一系列代碼封裝成動態庫,並在其中放入描述其接口的頭文件, 這樣作出來的東西就是框架。 48.多用枚舉塊,少用for循環 for in 和 block遍歷方式。 block遍歷方式能夠根據options 反向遍歷。 49.對自定義其內存管理語義的collection使用無縫橋接 __bridge 50.構建緩存是使用NSCache而非NSdictionary。 NSCache會在當系統資源耗盡時,它能夠自動刪除緩存。 先刪除最久沒使用的對象。 而且它也是線程安全的。 51.精簡initialize和load的實現代碼 若是分類和類都定義了load方法,先調用類的,在調用分類的。 整個應用程序在執行load時都會阻塞,因此load方法要精簡。 initialize 方法是懶加載的。只有當程序用到了相關的類,纔會調用。且只調用一次。 它也只應該設置類內部數據,不該該調用其它方法。 52.NSTimer會保留其目標對象 若是你的應用在iOS10以後,直接使用block方式建立就能夠避免對象不釋放這個問題。 也可使用NSWeakTimer三方庫解決。