【问题标题】:Objective-C Properties and Memory ManagementObjective-C 属性和内存管理
【发布时间】:2010-02-18 22:57:44
【问题描述】:

给定以下属性定义:

@property (nonatomic,retain) MyObject* foo;

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

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

?

看起来 alloc 调用将对象上的保留计数增加到 1,然后属性设置器中的保留将其增加到 1。但是由于初始计数从不减少到 0,因此即使当 self发行了。这个分析正确吗?

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

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

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

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

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

【问题讨论】:

    标签: objective-c properties


    【解决方案1】:

    还有其他选择吗?

    没有。

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

    您可以在 MyObject 上使用执行 alloc/init/autorelease 的类方法来清理它。

    + (MyObject *)object {
        return [[[MyObject alloc] init] autorelease];
    }
    
    self.foo = [MyObject object];
    

    【讨论】:

    • 这是一个很好的选择,可以在创建实例时节省时间。
    【解决方案2】:

    在 iPhone 上管理保留属性的最简单方法如下(自动释放并没有您想象的那么糟糕,至少对于大多数用途而言):

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

    autorelease 释放对分配给 self.object 的浮动实例的引用,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;
    }
    

    【讨论】:

    • -1 表示不调用[super init][super dealloc],这是危险的。
    • 我的错误,我只是指出了 someObject 分配方法。代码已更新。
    • 还是错了,事实上的init方法是把[super init]的返回值赋给self
    【解决方案3】:

    你是对的,self.foo = [[MyObject alloc] init]; 正在泄漏内存。两种选择都是正确的并且可以使用。关于autorelease 在这样的声明中:请记住,一旦当前运行循环结束,自动释放池就会释放对象,但self 很可能会保留更长的时间,所以没有这里的内存使用高峰问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多