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 }
相关文章
相关标签/搜索