ios - UINavigationController 中发生的魔术导致我的弱引用不恰当地归零
问题描述
让我从说我的办公室里没有直立的办公桌开始这个问题。我把它们都翻过来了。我需要帮助了解 Apple 中发生的UINavigationController
导致我对零值的弱引用。
首先,在我更详细地解释问题之前,让我提供代码来重现。
首先,创建一个UINavigationController
. 这个子类将持有对子类的弱引用UIViewController
。它应该是对将作为根视图控制器传入的内容的引用。
为了证明我的精神错乱,我提供了一个重现问题的初始化程序以及一个解决我的问题的初始化程序。为了完整起见,我已经包含了编译所需的其他初始化程序。
class ChildNavController: UINavigationController {
weak var weakRoot: UIViewController?
init(withWeakFirst: Void) {
let root = UIViewController()
print("rootVC: \(root)")
weakRoot = root
super.init(rootViewController: root)
}
init(withWeakLast: Void) {
let root = UIViewController()
print("rootVC: \(root)")
super.init(rootViewController: root)
weakRoot = root
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
}
这些print
语句是完全没有必要的,但我已经将它们包括在内,因为 a 的默认描述UIViewController
包括内存地址。
现在......测试正在发生的事情的代码,这是相当直接的......
首先,测试我的第一个初始化程序:
let weakFirst = ChildNavController(withWeakFirst: ())
if let _ = weakFirst.weakRoot {
print("weak first non-nil")
}
else {
print("weak first nil")
print("but the rootVC? \(weakFirst.viewControllers.first)")
}
控制台输出是:
rootVC: <UIViewController: 0x7f9de9f091a0>
weak first nil
but the rootVC? Optional(<UIViewController: 0x7f9de9f091a0>)
并将其与第二个初始化程序进行比较,在第二个初始化程序中,我只需更改调用 super.init 和分配到我的弱属性之间的顺序:
let strongFirst = ChildNavController(withWeakLast: ())
if let _ = strongFirst.weakRoot {
print("weak last non-nil")
}
else {
print("weak last nil")
print("but the rootVC? \(weakFirst.viewControllers.first)")
}
以及为此的控制台输出:
rootVC: <UIViewController: 0x7f9de9d11f70>
weak last non-nil
这里只有三行相关的代码。第一行初始化一个正则UIViewController
:
let root = UIViewController()
这被分配到一个局部变量中。当初始化器返回时局部变量消失,所以如果没有创建外部强引用,视图控制器应该被释放。
然后我还有两行。
weakRoot = root
和
super.init(rootViewController: root)
不知何故,这两行的顺序决定了我的weakRoot
属性是nil
还是对 . 的第 0 个索引中包含的同一对象的引用super.viewControllers
。
这对我来说没有意义,我需要帮助了解发生了什么。
附录:我尝试用我自己的超类重现这个问题。我尝试过使用 Swift 超类和 Objective-C 超类。在这些情况下,我无法重现该问题。我只能重现UINavigationController
(但是我不知道是否有其他 Apple 框架类可以复制这种行为)。
解决方案
推荐阅读
- angular - 在 Angular 中一次创建一些组件
- actionscript-3 - 如何防止 UI 在调用进程时锁定在 AIR 中?
- javascript - 代码第一次不起作用。无法解决问题
- node.js - 找不到“内容”命令
- git - 如何用另一个分支的提交覆盖旧提交?
- c++ - 使用这些原子操作与内存顺序放松和 rel/acq 如图所示,这个 C++ 片段是否有效?
- python - 如何调试停止的`ProcessPoolExecutor`?
- php - 如何搜索两个以上的关键字?
- mysql - 我们可以在 mysql 组复制中使用 REPEATABLE-READ 隔离级别吗?
- php - FB Marketing API - 支付系统被屏蔽,但广告账户没问题