您的位置:首页 > 移动开发 > Objective-C

Objective-C内存管理

2013-12-14 17:28 183 查看
1. Objective-C指针赋值时,retainCount不会自动增加,需要手动retain。

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


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

ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain count = 1
ClassA *obj2 = obj1;     //retain count = 1
[obj2 retain];     //retain count = 2
[obj1 hello];     //输出hello
//对于obj1,无需调用(实际上不能调用)
release [obj2 hello];     //输出hello
[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一个空指针是合法的,但不会发生任何事情)。

[obj1 release];
obj1 = nil;


ClassA *obj2 = obj1;
[obj2 retain];
//do something
[obj2 release];
obj2 = nil;


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

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

ClassA *Func1()
{
ClassA *obj = [[[ClassA alloc]init]autorelease];
return obj;
}


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

int main (int argc, const char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int i, j;
for (i = 0; i < 100; i++ )
{
         @autoreleasePool
          {
    for (j = 0; j < 100000; j++ )
    [NSString stringWithFormat:@"1234567890"];//产生的对象是autorelease的。
}
}
return (0);
} // main


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

-(void) dealloc
{
…
[super dealloc];
}


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

@interface ClassA : NSObject
{
ClassB* _objB;
}
@property (retain) ClassB* objB;
@end

@implementation ClassA
@synthesize objB;
-(void) dealloc
{
[_objB release];
         [super dealloc];
}
@end


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

self.objB 或者 objA.objB


12. 自己管好自己就行。如果获得了一个其他方法提供的对象,则不需要考虑该对象的内存管理问题,不必执行任何操作。但是,如果想要在一段时间内使用该对象,则需要保留retain该对象,并在使用完成后(在dealloc方法中)将其释放release。必须保持retain方法和release方法的使用次数相等。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: