1、MRC 手動引用計數程序員
一個對象 alloc 以後其引用計數爲1,須要對應一個 release 操做,此外,每有一個 retain 操做也要對應一個 release 操做。當一個對象的引用計數爲0時(能夠經過 retainCount 來獲取,但不必定準確),就會銷燬該對象,並調用該對象的 dealloc 方法。函數
對於對象組合的狀況,當一個對象使用另外一個對象時,須要使其引用計數+1,好比set方法,但若是set先後爲同一個對象,會致使引用計數變多,此時須要判斷set的新對象不是原成員對象,而後對原成員對象 release ,而對新對象進行 retain,該操做能夠經過 @property (retain) 來智能完成。atom
當兩個對象互相引用時,向上面的操做也會使引用計數錯誤(多1),此時能夠將其中一個對象的引用設置成 assign ,並在其 dealloc 函數中取消該成員的 release 操做。spa
總體代碼以下:指針
1 #import <Foundation/Foundation.h>
2
3 @class Room; 4 @class User; 5
6 /******************************/
7 @interface User : NSObject 8
9 //@property(nonatomic,retain) Room *room;
10 @property(nonatomic,assign) Room *room; 11
12 @end
13
14 @implementation User 15
16 - (void)dealloc 17 { 18 NSLog(@"%s",__func__); 19 //[_room release];
20 [super dealloc]; 21 } 22
23 @end
24
25 /******************************/
26 @interface Room : NSObject 27
28 @property(nonatomic,retain)User *user; 29
30 @end
31
32 @implementation Room 33
34 - (void)dealloc 35 { 36 NSLog(@"%s",__func__); 37
38 [_user release]; 39 [super dealloc]; 40 } 41 @end
42
43 /******************************/
44 int main(int argc, const char * argv[]) { 45 User *user = [[User alloc] init]; 46 Room *room = [[Room alloc] init]; 47 user.room = room; 48 room.user = user; 49
50 [user release]; 51 [room release]; 52 }
自動釋放池是以棧的結構存在的,先進後出。經過 @autoreleasepool 代碼段建立自動釋放池,在代碼段內調用對象的 autorelease 方法就能夠將對象放入自動釋放池,在自動釋放池生命週期結束時,會將該對象的引用計數-1。改寫 main 函數以下:code
1 int main(int argc, const char * argv[]) { 2 @autoreleasepool { 3 User *user = [[[User alloc] init] autorelease]; 4 Room *room = [[[Room alloc] init] autorelease]; 5
6 user.room = room; 7 room.user = user; 8
9 //[user release]; 10 //[room release];
11 } 12
13 //IOS5以前的老代碼還能夠這樣建立自動釋放池,如今不推薦,能看懂便可。
14 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 15 //coding
16 [pool release]; 17
18 return 0; 19 }
由於自動釋放池使用的是延遲釋放機制,因此不推薦將很是佔內存的對象交給自動釋放池管理,此外還有一些細節,好比不適宜在循環體內建立的對象交給同一個自動釋放池管理。 自動釋放池能夠嵌套,而自動釋放池也是棧結構,將一個對象進行 autorelease 操做,會自動將該對象放於棧頂的釋放池進行管理。對象
Foundation 庫中幾乎全部的類工廠方法,都是內部使用了 autorelease 方法。 blog
2、ARC 自動引用計數生命週期
是編譯器特性而不是運行時特性,不一樣於其它語言中的垃圾回收。它不容許程序員在程序手動調用 retain/release/autorelease 方法。內存
ARC的判斷原則:只要還有一個強指針(__strong,對應的弱指針爲 __weak)變量指向對象,對象就會保持在內存中。好比惟一的強指針變量超出生命週期,或者手動設置該強指針變量爲 nil,都會觸發 ARC 銷燬指向的對象。因此開發中,不要使用一個弱指針保存一個剛剛建立的對象,由於一建立就被銷燬了。
ARC中,若是一個對象想擁有另外一個對象,只須要用一個強指針指向該對象,@property 中不使用 retain,而是使用 strong/weak/assign。
與 MRC 相似,當兩個對象互相引用時,則一邊使用 strong ,一邊使用 weak。
Xcode 支持將 MRC 項目轉化成 ARC 項目,也能夠本身轉換,上面的例子轉成 ARC 項目以下:
1 #import <Foundation/Foundation.h>
2
3 @class Room; 4 @class User; 5
6 /******************************/
7 @interface User : NSObject 8
9 @property(nonatomic,weak) Room *room; 10
11 @end
12
13 @implementation User 14
15 - (void)dealloc 16 { 17 NSLog(@"%s",__func__); 18 } 19
20 @end
21
22 /******************************/
23 @interface Room : NSObject 24
25 @property(nonatomic,strong)User *user; 26
27 @end
28
29 @implementation Room 30
31 - (void)dealloc 32 { 33 NSLog(@"%s",__func__); 34
35 } 36 @end
37
38 /******************************/
39 int main(int argc, const char * argv[]) { 40 User *user = [[User alloc] init]; 41 Room *room = [[Room alloc] init]; 42
43 user.room = room; 44 room.user = user; 45 return 0; 46 }