1. 程式人生 > >Objective-C高階程式設計:iOS與OS X多執行緒和記憶體管理讀書筆記

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 * “