代码之家  ›  专栏  ›  技术社区  ›  Bill

目标C属性和内存管理

  •  5
  • Bill  · 技术社区  · 16 年前

    给定以下属性定义:

    @property (nonatomic,retain) MyObject* foo;
    

    以下代码是否导致内存泄漏:

    self.foo = [[MyObject alloc] init];
    

    ?

    看起来alloc调用将对象的保留计数增加到1,然后属性setter中的保留将其增加到1。但由于初始计数从未减为0,所以即使释放了self,对象也会一直存在。分析正确吗?

    如果是这样,看起来我有两种选择:

    self.foo = [[[MyObject alloc] init] autorelease];
    

    出于性能原因,不建议在iPhone上使用,或:

    MyObject* x = [[MyObject alloc] init];
    self.foo = x
    [x release];
    

    这有点麻烦。还有其他选择吗?

    3 回复  |  直到 15 年前
        1
  •  2
  •   MrMage    16 年前

    你是对的, self.foo = [[MyObject alloc] init]; 正在泄漏内存。两种选择都是正确的,可以使用。关于 autorelease 在这样的语句中:请记住,对象将在当前运行循环结束时由自动释放池释放,但很可能在 self ,所以这里的内存使用峰值没有问题。

        2
  •  3
  •   Gerry Shaw    16 年前

    有什么选择吗?

    不。

    如果不使用autorelease,你将无法编写大量的iPhone应用程序,而cocoa touch库在许多地方都使用它们。了解它在做什么(将指针添加到列表中以便在下一帧中删除),并避免在紧密循环中使用它。

    您可以在myObject上使用类方法,该方法为您分配/init/autorelease以清除它。

    + (MyObject *)object {
        return [[[MyObject alloc] init] autorelease];
    }
    
    self.foo = [MyObject object];
    
        3
  •  3
  •   Nick Bedford    16 年前

    在iPhone上管理保留财产的最简单方法如下(Autorelease并不像你想象的那么糟糕,至少在大多数情况下是这样的):

    -(id)init {
        if (self = [super init]) {
            self.someObject = [[[Object alloc] init] autorelease];
        }
        return self;
    }
    
    -(void)dealloc {
        [someObject release];
        [super dealloc];
    }
    

    这个 autorelease 释放对分配给的浮动实例的引用 self.object 它保留了它自己的引用,留给您需要的一个引用( someObject )。然后,当类被销毁时,将释放唯一剩余的引用,从而销毁对象。

    如另一个答案中所述,您还可以创建一个或多个“构造函数”消息,以创建具有可选参数的对象并自动释放。

    +(Object)object;
    +(Object)objectWithCount:(int)count;
    +(Object)objectFromFile:(NSString *)path;
    

    我们可以将其定义为:

    // No need to release o if fails because its already autoreleased
    +(Object)objectFromFile:(NSString *)path {
        Object *o = [[[Object alloc] init] autorelease];
        if (![o loadFromFile:path]) {
            return nil;
        }
        return o;
    }