繁体   English   中英

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

[英]Why would I ever use unowned self?

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的保护开发人员免受可能导致崩溃的常见错误的理念。

unownedweak相比具有边际性能优势,因为当对象消失时,运行时不必跟踪引用以将其转换为nil

关于保留周期(好的,强参考周期),既不weak也不unowned创建一个强引用(在ARC之前的术语中,既不增加保留计数)所以没有参考周期的危险,事实上,这就是为什么你需要在闭包中指定self weakunowned

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

除非有一个非常好的表现理由,否则我总是使用weak

在你的代码中注意,我认为这两个都没有必要,因为闭包没有转义,即函数调用foo中对它的引用在foo的作用域结束后不会持久存在。

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

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

根据Swit编程指南:自动引用计数

一个无主参考应该总是有一个值。 因此,ARC永远不会将无主引用的值设置为nil,这意味着使用非可选类型定义无主引用。

简而言之, weakunowned ,其中unowned者。

在导航控制器中使用无主参考的简单示例:

class RegisterViewController: UIViewController {
    lazy var navigatinRightBarItemsCount: Int = { [unowned self] in
        guard let navigationController = self.navigationController else { return 0 }
        guard let topItem = navigationController.navigationBar.topItem else { return 0 }
        guard let rightBarButtonItems = topItem.rightBarButtonItems else { return 0 }
        return rightBarButtonItems.count
        }()

    override func viewWillAppear(_ animated: Bool) {
        print("Navigation bar right side items count: ", navigationRightBarItemsCount)
    }
}

这意味着RegisterViewController必须初始化,而不是我们可以安全地获得自我。 navigationController并从这里获取项目数。 如果你试图把它变成[弱自我],XCode会抱怨因为self(viewcontroller)可以是nil,所以我们必须使用unowned。

UIBarButtonItem的另一个例子

lazy final private var filterNavigationBarItem: UIBarButtonItem = { [unowned self] in
    return UIBarButtonItem(image: #imageLiteral(resourceName: "filter_icon"),
                           style: .plain,
                           target: self,
                           action: #selector(segueToFilterJobs))
    }()

我们在这看到什么? 请参阅目标,该目标代表“ 接收操作消息的对象。 ”这意味着接收操作消息的对象不能为零并且必须初始化。

本文中来自drewag的一个非常好的解释

您真正想要使用[无主自我]或[弱自我]的唯一时间是您创建一个强大的参考周期。 一个强大的参考周期是当存在一个所有权循环,其中对象最终彼此拥有(可能通过第三方),因此它们将永远不会被释放,因为它们都确保彼此坚持。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM