UINavigationController中发生魔术,导致我的弱引用不适当地归零

时间:2018-08-14 20:27:59

标签: ios swift uinavigationcontroller initialization uikit

让我从开始陈述这个问题开始,说我的办公室里没有剩余的直立书桌。我把它们都翻过来了。我需要帮助来了解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语句是绝对不必要的,但是我将它们包括在内是因为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还是对super.viewControllers的第0个索引中包含的同一对象的引用。

这对我来说没有意义,我需要帮助来了解正在发生的事情。


附录:我尝试用自己的超类重现此问题。我已经尝试过Swift超级类和Objective-C超级类。在这些情况下,我无法重现该问题。我只能用UINavigationController复制(但是我不知道是否可能有其他Apple框架类复制此行为)。

0 个答案:

没有答案