Objective-C高階程式設計:iOS與OS X多執行緒和記憶體管理讀書筆記
Objective-C高階程式設計:iOS與OS X多執行緒和記憶體管理
自動引用計數
自動引用計數(ARC,Automatic Reference Counting)
“在LLVM編輯器中設定ARC為有效狀態,就無需再次鍵入retain或者是release程式碼”
引用計數的記憶體管理
生成物件->持有物件->釋放物件->廢棄物件
記憶體管理的思考方式
- 自己生成的物件,自己所持有
- 非自己生成的物件,自己也能持有
- 不在需要自己持有的物件時釋放
- 非自己持有的物件無法釋放
物件操作與Objective-C方法的對應
物件操作 | Objective-C方法 |
---|---|
生成並持有物件 | alloc/new/copy/mutableCopy等 |
持有物件 | retain |
釋放物件 | release |
廢棄物件 | dealloc |
Objective-C記憶體管理方法並不包括在該語言中,而是包含在Cocoa框架中用於iOS、OS X開發。Cocoa框架中Foundation框架類庫的NSObject類擔負著記憶體管理的職責。其中alloc/retain/release/dealloc方法分別指的是NSObject類中的alloc類方法,retain例項方法,release例項方法,dealloc例項方法( +alloc、-retain、-release、 -deallc)。
自己生成的物件,自己所持有
- alloc
- new
- copy
- mutableCopy
alloc方法
id obj = [[NSObject alloc] init];
//自己生成持有物件
new方法
id obj = [NSObject new];
//自己生成持有物件
copy方法利用基於NSCopying方法約定,由各類實現的copyWithZone:方法生成並持有該物件副本。
mutableCopy方法基於NSMutableCopying方法約定由各類實現的mutableCopyWithZone:方法生成並持有該物件副本。
非自己生成的物件,自己也能持有
這裡用NSMutableArray類的array類方法舉例:
id obj = [NSMutableArray array];
//取得非自己生成的物件,但自己並不持有
[obj retain];
// 自己持有物件
通過retain方法使非自己生成的物件成為自己所持有的。
不在需要自己持有的物件時釋放
id obj = [[NSObject alloc] init];
//自己生成持有物件
[obj release];
//釋放物件
id obj = [NSMutableArray array];
//取得非自己生成的物件,但自己並不持有
[obj retain];
// 自己持有物件
[obj release];
//釋放物件
用alloc等方法生成並自己持有的物件,用release方法釋放
用retain方法持有非自己生成的物件,也用release方法釋放
用上面方法持有的物件在不使用時要用release方法釋放
ARC規則
所有權修飾符
OC中為了處理物件,可將變數型別定義成id型別或者各種物件型別(指向NSObject這樣的的Objective-C類的指標,如NSObject*)。
ARC有效時,id型別和物件型別和C語言其他型別不同,一定要加上所有權修飾符。
- _ _strong 修飾符
- _ _weak 修飾符
- _ _unsafe_unretained 修飾符
- _ _autoreleasing 修飾符
在沒有明確指定所有修飾符時預設為_ _strong 修飾符,
_ _strong 修飾符表示對物件的強引用,持有其變數,在超出其作用域時被廢棄,隨著強引用的消失,引用的物件也會隨之釋放。
_ _unsafe_unretained 修飾符
和weak一樣並不能持有物件,所以生成的物件會被立即釋放。
在使用_ _unsafe_unretained 修飾符時,賦值給附有__strong修飾符的變數時要確保被賦值的物件存在。
_ _unsafe_unretained在iOS5在沒有引入__weak之前使用現在基本不使用了。
關於_ strong和 _weak的區別我覺得下面這篇文章講的很清楚、更直觀,比這本書中講到要直觀很多。
strong和weak
為什麼會出現這兩種修飾符?
因為 _strong並不能解決記憶體管理中一些問題,其中就是迴圈引用、類成員變數的迴圈引用(互相強引用)、對自身的強引用問題,這些很容易造成記憶體洩漏,應該廢棄的物件在超出其生命週期後繼續存在。這時使用 _weak 修飾符就不會造成迴圈引用。因為使用 _weak時並不持有該物件,所以不會出現應該廢棄的物件在超出其生命週期後繼續存在。
ARC規則
- 不能使用retain/release/retainCount/autorelease
- 不能使用NSAllocateObject/NSDeallocateObject
- 必須遵守記憶體管理的命名規則
- 不要顯示呼叫dealloc
- 使用@autoreleasepool塊替代NSAutoreleasePool;
- 不能使用區域(NSZone)
- 物件型變數不能作為C語言結構體(struct/union)的成員
- 顯示轉換”id”和”void * “