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