【问题标题】:Is releasing memory of Objective-c 2.0 properties required?是否需要释放 Objective-c 2.0 属性的内存?
【发布时间】:2009-09-07 12:25:07
【问题描述】:

我一直想知道关于属性的事情。在使用属性时,是否需要覆盖发布消息以确保属性是已发布的属性?

以下(虚构的)示例是否足够?

@interface MyList : NSObject {
NSString* operation;
NSString* link;
}
@property (retain) NSString* operation;
@property (retain) NSString* link;
@end

@implementation MyList
@synthesize operation,link;
@end

【问题讨论】:

  • 因为 NSString 确认到 NSCopying 协议,所以最好使用 @property (copy, readwrite) NSString *操作另外,如果你使用现代运行时,你不需要指定实例变量:它们也将被合成。要了解更多信息,请搜索 Apple 的“Objective-C 2.0 编程指南”并查找名为“Property Declaration Attributes”和“Property Implementation Directives”的部分。
  • +1 个很好的问题,想知道同样的事情

标签: objective-c cocoa


【解决方案1】:

您应该始终在 dealloc 中释放支持变量:

- (void) dealloc {
   [operation release];
   [link release];

   [super dealloc];
}

另一种方式:

- (void) dealloc {
   self.operation = nil;
   self.link = nil;

   [super dealloc];
}

这不是释放对象的首选方式,但如果您使用综合支持变量,这是唯一的方法。

注意:为了弄清楚为什么会这样,让我们​​看看 link 属性的 setter 的综合实现,以及当它设置为 nil 时会发生什么:

- (void) setLink:(MyClass *) value {
   [value retain]; // calls [nil retain], which does nothing
   [link release]; // releases the backing variable (ivar)
   link = value;   // sets the backing variable (ivar) to nil
}

所以最终效果是它会释放 ivar。

【讨论】:

  • 实际上,如果您使用的是合成 ivars(即您声明了属性但没有声明相应的 ivar),那么将为您生成一个 ivar。在这里查看我的问题:stackoverflow.com/questions/1283419
  • 一些编译器没有合成 ivar。在第一个支持合成 ivars 的编译器发布后,该问题得到了修复。因此混乱。
  • 更好的是,从托管内存转移到垃圾收集。那么,这个例子就可以写好了。
  • 大声笑,一个Java开发者(:
  • @Jacob — 你知道 Objective-C 2.0 引入了垃圾回收,对吗?它可能不适用于所有情况(例如 iPhone 或使用不支持它的框架时),但当您可以使用它时,它是一个很好的解决方案,尤其是在 Snow Leopard 中的改进后。垃圾收集器往往非常聪明和快速。 :-)
【解决方案2】:

非 GC 应用程序中,可以。通常分配 nil 而不是释放 ivars。 我最好的经验是释放使用 init 初始化的 ivars 并将 nil 分配给具有保留和复制模式的属性。

在你的情况下,我会分配 nil

- (void) dealloc {
   self.operation = nil;
   self.link = nil;
   [super dealloc];
}

【讨论】:

  • @gs 不正确。您可以释放 ivar 并将它们直接设置为 nil。在极少数情况下,使用访问器可能会产生奇怪的副作用。如果您正在观察对象的属性,并且该对象设置为 nil,则您的观察者可能会尝试从 obj 获取其他信息,但如果设置为 nil 发生在 -dealloc 中,则可能会发生奇怪的事情。
  • 这是语法的一个怪癖。一个人希望合成或隐含的“@properties_release();”在将来的某些语言规范中,可以将其添加到 dealloc 方法中。如果 Objective-C 2.0 对所有人来说都是万能的,那么推荐类似这种访问器语法的东西似乎很奇怪,然后不得不对析构函数中的观察者和属性访问器提出警告。
【解决方案3】:

最好的方法是:

- (void)dealloc {
    [operation release], operation = nil;
    [link release], link = nil;

    [super dealloc];
}

使用生成的setter方法确实会更方便

self.operation = nil;

但这是不受欢迎的。您并不总是知道对象在哪个线程上被释放。因此,使用访问器可能会通过触发 KVO 通知而导致问题。

这里的问题是您需要调整您的 dealloc 以匹配您的 @property 中定义的对象管理策略。例如。不要发布支持(分配)属性的 iVar。

【讨论】:

    【解决方案4】:

    不,您覆盖了-dealloc 方法。是的,如果你不释放你的属性(或者更确切地说,支持 ivars),你就会泄漏。所以在你的@implementation 中你应该有类似

    - (void)dealloc {
        [operation release];
        [link release];
        [super dealloc];
    }
    

    【讨论】:

      【解决方案5】:

      合成一个属性只会创建getter和setter方法,因此在释放对象时不会释放ivar。您需要自己释放 ivar。

      【讨论】:

      • 这仅适用于声明的属性使用默认(分配)属性。搜索 Apple 的“Objective-c 2.0 编程指南”并阅读“声明的属性”部分,尤其是关于 dealloc 的部分。我引用:“然而,声明的属性确实提供了一种有用的方法来交叉检查你的 dealloc 方法的实现:你可以在你的头文件中查找所有的属性声明,并确保没有标记为 assign 的对象属性被释放,并且那些标记为分配的人不会被释放。”
      【解决方案6】:

      在 pre-ARC 中,每当您看到 new、alloc、retain 和 copy 时,无论是实例 var 还是您必须释放的属性。在 ARC 中,只要你有一个强变量,你就必须将它设置为 nil。 无论哪种情况,您都必须覆盖 dealloc()。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-29
        • 1970-01-01
        • 2014-10-05
        • 2019-04-21
        • 2011-03-16
        • 2011-02-20
        相关资源
        最近更新 更多