OC內存管理

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 }
相關文章
相關標籤/搜索