【发布时间】:2011-12-06 22:53:25
【问题描述】:
我将我的应用程序转换为 ARC,并注意到在我的一个视图控制器中分配的对象在该视图控制器被解除分配时没有被解除分配。花了一段时间才弄清楚为什么。我在调试时为我的项目启用了“启用僵尸对象”,结果证明这是原因。考虑以下应用逻辑:
1) 用户在 RootViewController 中调用操作,导致 SecondaryViewController 创建并通过 presentModalViewController:animated 呈现。
2) SecondaryViewController 包含一个 ActionsController,它是一个 NSObject 子类。
3) ActionsController 在初始化时通过NSNotificationCenter 观察通知,并在解除分配时停止观察。
4) 用户关闭SecondaryViewController 以返回RootViewController。
启用僵尸对象关闭后,上述工作正常,所有对象都被释放。在 ActionsController 上启用 Zombie Objects 时,即使 SecondaryViewController 已被释放,也不会被释放。
这导致我的应用程序 b/c 出现问题 NSNotificationCenter 继续向 ActionsController 发送通知,由此产生的处理程序导致应用程序崩溃。
我在https://github.com/xjones/XJARCTestApp 创建了一个简单的应用程序来说明这一点。查看启用/关闭启用僵尸对象的控制台日志以验证这一点。
问题
- 这是启用僵尸对象的正确行为吗?
- 我应该如何实现这种类型的逻辑来消除问题。我想继续使用启用僵尸对象。
编辑 #1:根据 Kevin 的建议,我已将其提交给 Apple 和 openradar,地址为 http://openradar.appspot.com/10537635。
编辑#2:澄清一个好的答案
首先,我是一名经验丰富的 iOS 开发人员,我完全了解 ARC、僵尸对象等。当然,如果我遗漏了什么,我很感激任何启发。
其次,对于这种特定崩溃,确实有一个解决方法是在 secondaryViewController 被释放时将 actionsController 作为观察者删除。我还发现,如果我在 secondaryViewController 被释放时明确设置 actionsController = nil,它将被释放。这两种方法都不是很好的解决方法 b/c 它们实际上要求您使用 ARC,但代码就像您没有使用 ARC 一样(例如,在 dealloc 中显式地使用 nil iVars)。特定的解决方案也无助于确定这在其他控制器中何时会成为问题,因此开发人员可以确定性地知道何时/如何解决此问题。
一个好的答案将解释如何确定性地知道在使用 ARC + NSZombieEnabled 时您需要对一个对象做一些特殊的事情,这样它就可以解决这个特定的例子,并且通常也适用于整个项目而不会留下潜力其他类似的问题。
完全有可能没有一个好的答案,因为这可能是 XCode 中的一个错误。
谢谢大家!
【问题讨论】:
-
这听起来像一个错误。请file a bug report 并附上您的示例项目。
-
感谢@Kevin,我已将错误报告提交给 Apple。
-
另外,您应该将
.DS_Store添加到您的全局 git 忽略中。 -
哎呀,我的 .gitconfig 搞砸了。感谢您关注@jim。
标签: iphone ios automatic-ref-counting nszombieenabled