问题 为什么我会使用无主的自我?


iOS应用程序中出现以下模式:

class MyViewController: UIViewController {
    let myModel = MyModel()

    override func viewDidLoad() {
        super.viewDidLoad()
        myModel.foo() { [***] in
            // use self here
        }
    }
}

class MyModel {
    public func foo(complete: () -> Void) {
        // do something
        complete()
    }
}

共识是使用其中之一 [unowned self] 要么 [weak self] 代替 [***]当你可以保证在完成时自我不会为零而且在你不确定引用仍然有效时会很弱的情况下,这是无主的。
我不明白为什么我会冒险使用无主,也许我确信现在参考永远不会是零,但这可能在未来发生变化。我也可能忽略了一个边缘案例,错误发生了。我可以很容易地总是使用弱,并在封闭的顶部放一个警卫,以便能够使用自己没有!要么 ?。
无主的用途是什么?它比弱+守卫更快吗?是语法糖吗?这似乎违背了Swift的保护开发人员免受可能导致崩溃的常见错误的理念。


12712
2017-09-25 14:17


起源

我不太清楚,但在其他语言中,这样的概念 [unowned] 对于与C等缺乏引用计数的其他语言的接口非常重要。虽然为什么人们会在你出席的环境中使用它超出我的范围。 - Cort Ammon


答案:


unowned 具有边际绩效优势 weak 因为运行时不必跟踪将其转换为的引用 nil 当物体消失时。

关于保留周期(好的,强参考周期),两者都没有 weak 也不 unowned 创建一个强引用(在预ARC术语中,既没有增加保留计数)所以没有参考周期的危险,事实上,这就是你需要指定的原因 weak 要么 unowned 对于 self 在关闭。

还有,用 unowned 您可以将引用用作非可选项,因此您不必在闭包中放置任何代码来解包它。

我总是用 weak 除非有一个非常好的表现理由不这样做。

在你的代码中注意,我认为没有必要,因为闭包没有转义,即函数调用中对它的引用 foo 结束后不会持续存在 foo的范围。


10
2017-09-25 14:24



在这两种情况下如何保留周期? ,它有区别吗? - Prashant Tukadiya
按照我的弱自我,保留周期没有一个可能性,但我不知道无主 - Prashant Tukadiya
@JonSnow unowned 也不是一个强有力的参考。 - JeremyP
“因为当对象消失时,运行时不必跟踪引用以将其转换为nil“ - 实际上并非如何 weak 引用在Swift运行时工作(尽管它确实是Obj-C运行时)。基本上,当对象形成弱引用时,对象获得跟踪其引用计数的“边表”(并将ptr保持为对象)。弱引用然后指向此边表。即使在对象被释放后,弱引用仍然指向该边表... - Hamish
...在加载弱引用时,检查强保留计数;如果它是零,那么 nil 被退回。然后,当弱保留计数达到零时,边表被解除分配。这篇博文是关于这个主题的好读物: mikeash.com/pyblog/...。尽管如此, unowned 由于这一事实,参考资料仍可能具有边际绩效优势 weak 引用将需要额外的解引用(从边表到对象)。 - Hamish


我相信使用 unowned 增加风险比使用弱自我。错误确实发生,它的一个例子是在视图控制器中启动API调用,让它等待响应到达并突然弹出视图控制器可能导致它被释放(如果没有强引用它)。当响应到来时,我们的视图控制器对象将消失,我们的应用程序将崩溃在我们的脸上。由我们来决定在哪个地方使用哪一个。

杰里米 指出, unowned 没有责任跟踪引用计数,因此它在强弱方面具有如此轻微的性能优势。


1
2017-09-25 14:29





按照 Swit编程指南:自动参考计数

预期无主参考值始终具有值。因此,ARC永远不会将无主引用的值设置为nil,这意味着使用非可选类型定义无主引用。

简而言之, weak 是选择,在哪里 unowned 不是。


0
2017-09-25 14:23



但为什么?看来使用无主只会引入无风险的风险。我宁愿玩它安全,总是使用弱,有一个守卫自己!=顶部的零。 - kevin
@kevin如果你的程序中有一个前提条件,那就是对象A. 一定不 生命对象B,然后对象A保持一个完全合理 unowned, 而不是 weak,对象B的引用。如果前提条件被破坏,您可能不希望应用程序以无提示状态继续静默;你希望它陷阱,所以你可以修复bug。这不是风险案例,而是确保您拥有一个结构良好的计划。 - Hamish
@Hamish +1这是有道理的。 - Badhan Ganesh