建立一個對象需要丙步:
1. 動態為新對象分配記憶體。
2. 將新分配的記憶體與相關的值產生關聯。
直到這兩步都做完,對象建立過程才算全部完成,雖然是兩個步聚,但是在編寫代碼的時候
通常使用一行代碼來完成:
id anObject = [[Rectangle alloc] init];
分離這兩個步驟給我們更多的選擇擇。
基底物件 NSObject 中的 alloc 和 allocWithZone 方法提供兩種分配方式 。
這兩個方法一般不需要在子類中覆寫。
它們為成員變數分配足夠的記憶體以供使用。
具體的步驟:
1. 初始化一個 isa 執行個體並指向 class object.
2. 將其它成員變數置為零。
對象還需要進行進一步的初始化才能正常工作。
初始化方法用 "init 開頭", 如 initWithFrame
關於返回的對象:
如果一個對象沒有被正確地初始化,那麼 alloc 方法返回的可能是一個Null 物件。
因此要保證最後得到的是一個合法的可工作的對象,應該進行必要檢查:
id anObject = [[SomeClass alloc] init];
if ( anObject )
[anObject someOtherMessage];
else
...
幾個初始化器的約定:
1. 初始化方法使用 init 開頭.
2. 初始化方法傳回值應該是是 id.
3. 自訂的初始化方法必調用基礎的初始化方法以完成底層的動作。
4. 需要將新建立的對象引用賦給 self 指標。
5. 在初始化器中給成員變數賦值應使用直接賦值而不是 accessor method.
6. 初始化器返回 self 指標或是 nil.
例子:
- (id)init {
// Assign self to value returned by super's designated initializer
// Designated initializer for NSObject is init
self = [super init];
if (self) {
//使用 if 判斷是為了避免初始化失敗。
creationDate = [[NSDate alloc] init];
}
return self;
}
當初始化對象失敗時:
需要執行 release() 方法並返回 nil
比如:
- (id)initWithImage:(NSImage *)anImage {
if (anImage == nil) {
[self release];
return nil;
}
...
初始化器只初始化自己的成員變數,父級類的成員變數由 self = [super init]; 進行初始化
每個類的 designated initializer 應該當保證它會調用父類的 designated initializer
如果使用者調用了無參數的 init 方法,那麼 init 方法內部應該使用預設參數調用一個 init 方法的其它 overload 方法.
某些類將 記憶體配置和初始化放到一起,稱為方法初始化方法。
兩個參考文檔:
記憶體管理:
http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocObjectsClasses.html#//apple_ref/doc/uid/TP30001163-CH11-142945
記憶體管理編程指南:
http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html#//apple_ref/doc/uid/10000011i
將初始化和記憶體配置操合并的好處:
1. 記憶體配置需要初始化方法提供一些額外的資訊.
2. 避免為新對象綁定了記憶體但是沒有使用。例用你傳進去了一個 name , 但是之前已經存在了一個同名的對象,這時就返回那個已存在的對象,
而新產生的對象還沒有使用就又被釋放了,或者想象一個單例模式,僅當 instance 對象不存在時才需要初始化和分配記憶體給一個新對象,否則
應該返回已存在的對象。