【问题标题】:Is it necessary to release the ivar and set the synthesized ivar to nil at the same time?是否需要同时释放ivar并将合成的ivar设置为nil?
【发布时间】:2009-06-16 21:32:56
【问题描述】:

我看到代码(可能是 Apple 自己的示例代码)以这样的方式编写,它在 dealloc 中释放 ivar 并在 viewDidUnload 中设置属性。

例如

- (void)viewDidUnload
{
  self.navigationController = nil;
}

- (void)dealloc
{
   [_navigationController release];
}

为什么他们在两个地方?另外,为什么在一个中设置 nil 并在另一个中释放。似乎 self.property = nil 会处理所有事情,因为它会释放并将 ivar 设置为 nil。

【问题讨论】:

    标签: objective-c


    【解决方案1】:

    你是对的:你确实可以在任何地方做self.property = nil,包括dealloc。唯一的缺点是,如果 setter 方法执行的操作比释放 ivar 更复杂,您最终可能会尝试访问已释放的其他字段,等等。

    至于为什么还要在viewDidUnload放出outlet,那是内存优化。由于您在viewDidUnload 中释放的内容会在视图再次加载时重新实例化,因此在内存不足的情况下释放它们会释放内存。

    【讨论】:

    • 谢谢,所以在这种情况下,viewDidUnload 代码可以使用与 dealloc 相同的代码来释放对象,即 [_navigationController release] 而不是将其设置为 nil,对吗?
    • 是的,但不要。除了 -dealloc 之外,在任何地方都使用访问器。由于 Daniel 给出的原因,在 -dealloc 中使用访问器是有争议的(Apple 也不清楚他们推荐什么)。只要养成在 -dealloc 中释放所有保留的 ivars 的习惯。不要赌其他事情会为你做这件事。每当你释放一些东西时,将它设置为 nil。 ObjC 的大部分内容都没有安全网;好的习惯是让你的程序正常工作的原因,因为编译器不会拯救你。 (好吧,也许 Clang 最终会拯救我们,但只能永远使用它的力量。)
    【解决方案2】:

    Apple 建议您不要在 init 中调用 setter,尤其是在 dealloc 例程中。

    这是因为此时对象只是部分设置,setter 可能会附加观察者,或者可能被子类覆盖,否则会在释放期间产生不良影响,或者在释放期间可能会混淆使用部分配置的对象进行初始化。

    因此,您通常使用:

    _navigationController = [[NavController alloc] init];
    

    在您的 init 例程中添加样式代码,

    [_navigationController release];
    

    dealloc 中的样式代码,以及已知对象已完全完成的其他代码中的 setter。

    需要考虑的一些情况:

    • 子类覆盖 setNavigationController 并引用它自己的由 init 分配的 ivars。初始化时崩溃。
    • 子类覆盖 setNavigationController 并引用它自己在 dealloc 中发布的 ivars。在 dealloc 上崩溃。
    • 子类覆盖 setNavigationController 并重绘屏幕的某些部分。毫无意义的循环浪费或显示故障。
    • 同时被释放的其他对象观察 navigationController 并且这些观察者在 dealloc 期间触发

    【讨论】:

      【解决方案3】:

      如果您依赖垃圾回收(在 Objective-C 2.0 中可用),那么将 ivar 设置为 nil 并调用 release 将达到相同的目的。

      我猜您正在查看的代码正在使用release 管理内存,并且仅将其设置为nil,以便您以后不会尝试访问不再存在的对象。当您不依赖 GC 时,nil 比内存管理更能记账。

      【讨论】:

      • 不完全 -- -[anObject release] 在 GC 下不会做任何事情(它是一个 nop),而设置为 nil 将允许垃圾收集器最终释放对象(它正在删除引用),除非 ivar 被定义为弱引用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-16
      • 2011-07-18
      • 1970-01-01
      • 1970-01-01
      • 2012-02-23
      • 1970-01-01
      • 2023-03-12
      相关资源
      最近更新 更多