Objective-C内存管理

1. Objective-C指针赋值时,retainCount不会自动增加,需要手动retain。

1 ClassA *obj1 = [[ClassA alloc] init];       //retain count = 1 
2 ClassA *obj2 = obj1;                             //retain count = 1 
3 [obj2 retain];                                         //retain count = 2 
4 [obj1 hello];                                           //输出hello     
5 [obj1 release];                                     //retain count = 2 – 1 = 1 
6 [obj2 relese];             //retain count = 0,对象被销毁                          

2. 新生成的对象只要调用autorelease就行了,无需再调用release!自动释放的对象不需要调用release,因为已经将释放的责任转交给了自动释放池。但是对于赋值的指针还是要调用release的!

1 ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain count = 1 
2 ClassA *obj2 = obj1;     //retain count = 1 
3 [obj2 retain];     //retain count = 2 
4 [obj1 hello];     //输出hello 
5                         //对于obj1,无需调用(实际上不能调用)
6 release [obj2 hello];     //输出hello 
7 [obj2 release];     //retain count = 2-1 = 1

3. NSAutoreleasePool内部包含一个数组(NSMutableArray),用来保存声明为autorelease的所有对象。如果一个对象声明为autorelease,系统所做的工作就是把这个对象加入到这个数组中去。NSAutoreleasePool自身在销毁的时候,会遍历一遍这个数组,release数组中的每个成员。如果此时数组中成员的retain count为1,那么release之后,retain count为0,对象正式被销毁。如果此时数组中成员的retain count大于1,那么release之后,retain count大于0,此对象依然没有被销毁,内存泄露。

而自动释放池之间以栈的形式实现:当你创建了一个新的自动释放池时,它被添加到栈顶。接受autorelease消息的对象将被放入最顶端的自动释放池中。如果将一个对象放入一个自动释放池中,然后创建一个新的自动释放池,再销毁新建的自动释放池,则这个自动释放池对象仍将存在,因为容纳该对象的自动释放池仍然存在。

4. Objective-C程序中可以嵌套创建多个autorelease pool。在需要大量创建局部变量的时候,可以创建内嵌的autorelease pool来及时释放内存。一般都是使用完对象之后马上进行释放,以将内存使用量保持在尽可能低的水平。

5. 如果你通过alloc、new或copy来创建一个对象,如果是临时对象,那么你必须在不再使用时手动调用release或autorelease来释放对象;如果希望在多段代码中一直拥有对象,作为其他对象的实例来使用,则只需确保在拥有该对象的dealloc方法中释放它即可。除了alloc、new或copy之外的方法创建的对象都被声明了autorelease。

6. retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用release。

7. 范式:Release一个对象后,立即把指针清空(顺便说一句,release一个空指针是合法的,但不会发生任何事情)。

1 [obj1 release]; 
2 obj1 = nil;
1 ClassA *obj2 = obj1; 
2 [obj2 retain]; 
3 //do something 
4 [obj2 release]; 
5 obj2 = nil;

8. 范式:在方法中创建的临时对象,在方法返回前需要对其进行释放。

在一个函数创建并返回对象,需要把这个对象设置为autorelease。这样,由于延迟释放,返回的对象不仅有效,而且保证会被自动释放池释放。

1 ClassA *Func1() 
2 3      ClassA *obj = [[[ClassA alloc]init]autorelease];  
4      return obj; 
5 }

如果程序的某个方法中需要创建很多临时对象,当方法执行完之后这些临时对象就没用了。如果整个程序只有一个释放池,则这些临时对象会一直无法释放,直至事件处理结束。所以,可以方法的开始处或循环中创建一个局部的自动释放池,在方法返回或退出循环之前释放自动释放池。这样所有该方法创建的临时对象会随着自动释放池的释放而释放。使用@autoreleasePool{},无须显示向某对象发送autorelease方法,所有花括号里的代码都会被自动放入这个新池子里,任何在花括号里定义的变量在括号外就无法使用了。

 1 int main (int argc, const char *argv[]) 
 2 { 
 3      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 4      int i, j; 
 5      for (i = 0; i < 100; i++ ) 
 6      { 
 7          @autoreleasePool
 8          {
 9           for (j = 0; j < 100000; j++ ) 
10              [NSString stringWithFormat:@"1234567890"];//产生的对象是autorelease的。 
12 } 13 } 14 return (0); 15 } // main

 

9. 范式:在子类的dealloc方法中调用基类的dealloc方法 。

1 -(void) dealloc 
2 { 
3 4         [super dealloc]; 
5 }

10. 范式:如果类中声明了具有保持copy和复制retain特性的属性,则需要在dealloc方法中release其成员变量

 1 @interface ClassA : NSObject 
 2  3         ClassB* _objB; 
 4 }   
 5 @property (retain) ClassB* objB; 
 6 @end   
 7 
 8 @implementation ClassA 
 9 @synthesize objB; 
10 -(void) dealloc 
11 12         [_objB release];
13         [super dealloc]; 
14 15 @end

11. 范式:除了dealloc方法以外,始终用.操作符的方式来调用property。 

1 self.objB 或者 objA.objB

12. 自己管好自己就行。如果获得了一个其他方法提供的对象,则不需要考虑该对象的内存管理问题,不必执行任何操作。但是,如果想要在一段时间内使用该对象,则需要保留retain该对象,并在使用完成后(在dealloc方法中)将其释放release。必须保持retain方法和release方法的使用次数相等。

 

 

posted on 2013-12-14 17:28  fuleying  阅读(720)  评论(2编辑  收藏  举报