Objective-C 入門
Object-C 是 C 的超集,它使用運行時來進行動態綁定,所有對象的類型都是在運行時才能確定的,都是以消息傳遞的機制運作;所有對象都是在heap中allocated的,在stack中allocate對象是不合法的;內存管理在objc中被抽象為以引用計數的方式來進行管理。
最小化在頭文件中import的頭文件數量,在盡可能的深處引用它;使用提前聲明,消除多余的引用,消除互相引用;使用 continuation category 細化類別 來減少 多余的類方法造成的 過多編譯量。
-
對于NSArray、NSNumber、NSDictionary的快捷初始化方法,使用literals語法,使代碼更加簡潔,更加安全,但只能創建immutable的對象,對于mutable的對象需要使用mutableCopy
NSMutableArray *mutable = [@[@1,@2,@3,@4,@5] mutableCopy];
-
選擇使用
static const NSIntger durantion = 1;
來代替
#define durantion 1
定義常量,優點在于避免重定義造成的錯誤、加入global symbol Table能多處使用、更加嚴格的類型定義
對象,消息與運行機制
-
最好用直接訪問的方法來讀取成員變量,而用property生成的setter方法來賦值成員變量;
直接賦值更加快速,但會失去了對成員變量制定的property屬性的內存控制;并且不會觸發對于該成員變量 KVO 監聽函數;
初始化函數中,最好對成員變量直接賦值,因為可能在子類中重載的setter方法會做出特殊的過濾處理;當然,如果該成 員變量只聲明在此類的父類中,那只能調用setter方法;
如果成員變量是使用lazy initialization 方法,如- (IFObject*)object { if(!_object) { _object = [IFObject new]; } return _object; }
那讀取它時需要調用它的getter方法,否則會出錯。
-
使用動態綁定對象,使代碼更優雅
void (^block)(NSInteger) = objc_getAssociatedObject(alertView, kAlertKey);
用Key獲取與該對象關聯的對象或block
可以視為Key/Value方式的擴展,需要 #import <objc/runtime.h>
在AlertView中,我們可以在聲明每個AlertView后將處理其點擊的delegate方法寫為block,與該alertView綁定,這樣能 夠避免同個類文件聲明多個AlertView后委托方法的臃腫不堪
同理,可應用在多個場景中。 使用
[object isKindOfClass:]
檢查是否為該類或其子類,使用[object isMemberOfClass:]
檢查是否為該類;
對象接口設計
- 在命名類時,多使用三字母前綴(避免與系統二字母前綴沖突)避免命名空間沖突;
引入第三方庫時,修改庫命名,加入自定義的前綴,以防多次引入第三方庫導致的命名空間沖突。 - 一個類必須只有一個指定的初始化方法,其他初始化方法都最終指向它;
在子類中只需要重載指定初始化方法即可; - 定義類的
description
方法,返回描述對象的NSString,使對象能被NSLog輸出;
若需要,定義類的dubugDescription
方法,提供更加詳細的描述方法; - 偏向immutable對象,防止mutable對象在運行時的修改導致程序異常;
盡可能類頭文件只暴露具有readonly屬性的property,若在類內部需要修改該成員變量,可使用直接訪問,或在class-continuation catalogy里將該property的屬性定義為readwrite;
提供一個修改類成員變量的公共方法,而不是將一個可變的成員變量暴露在頭文件中; - 在類接口命名上按照Objc的標準進行命名,在命名上表意清晰并完整,向句子一樣表述接口作用;
- 在Objc中,沒有一個能將類中成員或方法定義為private的方法,偏向用
p_
前綴修飾private變量與方法,以便于公共方法區分開來; - 若是程序發生致命錯誤,用
NSException
來拋出異常終止程序,在非致命錯誤上,返回nil或者0,或者返回一個NSError
對象通過委托方法等方式對錯誤進行處理;
委托與協議
使用delegate委托模型進行對象間的消息傳遞,優化點為可以使用緩存機制來保存委托對象的消息響應狀況(之后再寫文章詳細描述);
使用
categories
擴展類別技術分割類文件,實現類方法功能的分類,防止單一類文件代碼過于冗長;也可以創建一個private
的類別,表示類的私有方法;當自定義或引入
categories
時,盡可能加上自定義的前綴,以免與系統類別定義沖突;-
無法在
categories
類別(除continuation categories
)添加property
,在添加的類別中,property
成員變量是無法進行synthesized
,因此無法為property
提供getter
和setter
方法;解決方法只有自定義property
的訪問與修改方法,并加上@dynamic property
來表明
property
的的訪問與修改方法在運行時生成; -
在類的實現文件中使用class-continuation categories技術
@interface WYObject() //Property and method @end
這個類別可用于
- 可以添加成員變量與方法到類中,因此可以隱藏無需公開在頭文件的成員變量;
- 可以重新聲明頭文件中聲明的
property
,修改其屬性,如將readonly
改為readwrite
; - 聲明類的私有函數(可以不在類別中聲明,但這能增加可讀性);
- 能夠在類別中聲明類遵守的
protocols
協議,若該類不希望公開;
-
使用
protocol
協議來提供一個匿名類@property (nonatomic,weak) id<WYDelegate> delegate
當一個對象的類型需要被隱藏,或者對象實現了什么方法比對象類型更重要時,可以采用匿名類。
內存管理
盡管現在已經是ARC的年代了,但是ARC的本質是系統在程序的適當地方添加上內存管理代碼,因此對于內存管理的技術還是需要了解清楚地。
- 程序中,所有對象通過引用關系組成一張內存計數的對象圖,在一個對象的聲明周期中,對其的retain與release次數必須相等;
- 使用
@autureleasepool
內存池,加在大量動態內存生成的代碼中,使內存池立即釋放內存,防止內存高峰導致程序crash; - 禁止使用
retainCount
方法,因為在程序的某一刻,retainCount
返回的數值是不能確定的。