【问题标题】:Is it ok to call release on a property in Objective C?可以在 Objective C 中的属性上调用 release 吗?
【发布时间】:2011-09-01 10:30:42
【问题描述】:

我最近一直在自学 Objective C,并注意到以下模式在教程和示例代码(包括来自 Apple 网站的示例)中大量使用。

UIView *myUiView = [[UIView alloc] init];
self.uiView = myUiView;
[myUiView release];

我只是想知道,创建一个新变量似乎有点浪费,只是为了设置一个属性。我也看到过使用以下模式,但据我了解,在 iOS 设备上使用自动释放被认为是不好的形式,因为自动释放池占用了相当多的开销,这在移动设备上可能不好

self.uiView = [[[UIView alloc] init] autorelease];

我最近一直在玩弄使用以下模式,它设置属性,然后在属性上调用 release(以减少属性本身的引用计数器)。

self.uiView = [[UIView alloc] init];
[self.uiView release];

我已经设法在几个 ViewController 上使用它而没有任何不良影响,但这是有效的代码,还是我遗漏了一些使它成为一个坏主意的东西?

【问题讨论】:

标签: objective-c ios properties


【解决方案1】:

属性 getter 是一个方法,它不必返回一个 ivar,它实际上可以在任何地方获取它的返回值,所以你可以释放它,但它可能已经是一个自动释放的值。如果是这样,你就有麻烦了。

IOW,如果属性 getter 会做类似的事情(不常见,但可能且有效):

- (NSString *) helloString
{
    return [[myStringIVar copy] autorelease];
}

你做到了:

[self.helloString release];

那么你失败的原因有两种:

  • 你没有释放你想释放的 ivar
  • 您释放了一个自动释放的对象

IMO,最好直接释放 ivar:

[myStringIVar release];

【讨论】:

    【解决方案2】:

    如果属性 getter 的实现只是简单地返回对底层 ivar 的引用,那么它是完全等价的,您只需减少分配对象的保留计数。

    另一方面,如果你不能确定 getter 做了什么(如果它返回的不是 ivar,例如一些计算结果等),它可能是危险的。

    【讨论】:

    • +1。您也可以拥有没有 ivars 的属性,这使得这是一种危险的模式。并且应该避免释放 getter 返回的对象。
    【解决方案3】:

    没有。无效。

    它可能适用于大多数保留属性,但不一定。它可能会在复制属性和分配属性时中断。

    属性只是一对方法,其中一个设置一个抽象实体,一个获取它。 绝对不能保证 getter 会为您提供与您刚刚传递给 setter 完全相同的对象。 例如,如果您将可变字符串传递给 NSString 复制属性,您绝对不会取回同一个对象。

    使用前两种模式中的任何一种。第一个不浪费任何东西。局部变量很可能只存在于寄存器中。第二个的开销只会持续到下一个自动释放池耗尽的时间,并且只有几个字节(请记住,实际对象在任何情况下都会持续到self)。

    【讨论】:

      【解决方案4】:

      这是无效的,即使在它确实工作的情况下它有点“丑陋”,另外两个只是为了修复属性的保留特性,在分配已经使保留计数为 1 之后使保留计数为 2。

      我倾向于按照您在第一个示例或以下示例中描述的操作。

      在我的@interface 中

      @property (nonatomic, retain) UIView *uiView;
      

      在我的@实现中

      @synthesize uiView = _uiView;
      

      然后当我设置属性时。

      _uiView = [[UIView alloc] init];
      

      【讨论】:

      • 不,我在各个方面都是对的。事实上,我发现释放属性 getter 返回的对象违反了内存管理规则。
      • 嘿,这就是我要找的东西,我希望我能接受,尽管您的回答在技术上并不能回答我的问题。我会赞成一个好的解决方案:)
      【解决方案5】:

      从引用计数器的角度考虑,使用属性值调用release 没有任何问题。但是,有几件事是我(个人)不喜欢的:

      属性语法实际上只是方法调用的语法糖。所以,你的代码真正的样子是

      [self setUiView: [[UIView alloc] init]];
      [[self uiView] release];
      

      这里的另一件事可能更多是由于我以奇怪的方式思考,但我喜欢将引用计数视为实际上与引用相关。持有指向我的对象的指针的局部变量就是这样的引用。将它出现在代码中提醒我,我有一些事情要做才能正确清理(或者,如果没有,至少写一个简短的评论,为什么我不必清理)。

      直接通过属性迫使我考虑引用计数,我不喜欢。

      【讨论】:

        猜你喜欢
        • 2011-02-09
        • 2014-12-12
        • 2011-04-25
        • 2012-06-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-01
        • 1970-01-01
        相关资源
        最近更新 更多