简体   繁体   English

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

[英]Why would I ever use unowned self?

The following pattern happens a lot in iOS apps: 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()
    }
}

The consensus is to use either [unowned self] or [weak self] in place of the [***] , unowned when you can guarantee that self will not be nil at the time of completion and weak when you're not sure the reference will still be valid. 共识是使用[unowned self][weak self]代替[***] ,当你可以保证在完成时自我不会为零而在你不确定参考仍然有效。
What I don't understand is why I would ever risk using unowned, maybe I'm sure that right now the reference will never be nil, but that can change in the future. 我不明白为什么我会冒险使用无主,也许我确信现在参考永远不会是零,但这可能在未来发生变化。 I could also have overlooked an edge-case, mistakes happen. 我也可能忽略了一个边缘案例,错误发生了。 I could just as easily always use weak, and put a guard at the top of the closure to be able to use self without a ! 我可以很容易地总是使用弱,并在封闭的顶部放一个警卫,以便能够使用自己没有! or ?. 要么 ?。
What is the use of unowned? 无主的用途是什么? Is it faster than weak+guard? 它比弱+守卫更快吗? Is it syntactic sugar? 是语法糖吗? It seems to go against Swift's philosophy of protecting the developer against common mistakes that can cause crashes. 这似乎违背了Swift的保护开发人员免受可能导致崩溃的常见错误的理念。

unowned has a marginal performance advantage over weak because the runtime doesn't have to keep track of the reference to turn it into nil when the object goes away. unownedweak相比具有边际性能优势,因为当对象消失时,运行时不必跟踪引用以将其转换为nil

In respect of retain cycles (well, strong reference cycles), neither weak nor unowned creates a strong reference (in pre ARC terms, neither increments the retain count) so there is no danger of a reference cycle, in fact, that is why you need to specify weak or unowned for self in closures. 关于保留周期(好的,强参考周期),既不weak也不unowned创建一个强引用(在ARC之前的术语中,既不增加保留计数)所以没有参考周期的危险,事实上,这就是为什么你需要在闭包中指定self weakunowned

Also, with unowned you can use the reference as a non optional, so you don't have to put any code in the closure to unwrap it. 此外,对于unowned您可以将引用用作非可选项,因此您不必在闭包中放置任何代码来解包它。

I always use weak unless there is a really good performance reason not to. 除非有一个非常好的表现理由,否则我总是使用weak

NB in your code, I do not think either is necessary because the closure is not escaping ie The reference to it taken in the function call foo does not persist after the end of foo 's scope. 在你的代码中注意,我认为这两个都没有必要,因为闭包没有转义,即函数调用foo中对它的引用在foo的作用域结束后不会持久存在。

I believe that using unowned adds to the risk than using weak self. 我认为使用unowned增加了风险,而不是使用弱自我。 Mistakes do happen and one example of it would be starting an API call in a view controller, let it wait for the response to arrive and suddenly popping that view controller may cause it to get deallocated (If there are no strong references to it). 错误确实发生,它的一个例子是在视图控制器中启动API调用,让它等待响应到达并突然弹出视图控制器可能导致它被解除分配(如果没有强引用它)。 By the time when the response arrives, our view controller object would be gone, and our app will crash on our face. 当响应到来时,我们的视图控制器对象将消失,我们的应用程序将崩溃在我们的脸上。 It is up to us to decide which one to use in which place. 由我们决定在哪个地方使用哪一个。

As Jeremy pointed out, unowned does not have the responsibility to keep track of the reference count, so it has ever so slight performance advantage over strong and weak. 正如杰里米指出的那样, unowned并没有责任跟踪引用计数,因此它在强弱方面具有如此微小的性能优势。

As per Swit Programming Guide: Automatic Reference Counting 根据Swit编程指南:自动引用计数

An unowned reference is expected to always have a value. 一个无主参考应该总是有一个值。 As a result, ARC never sets an unowned reference's value to nil, which means that unowned references are defined using nonoptional types. 因此,ARC永远不会将无主引用的值设置为nil,这意味着使用非可选类型定义无主引用。

In short, weak are optionals, where unowned are not. 简而言之, weakunowned ,其中unowned者。

An simple example of using unowned reference in navigation controller: 在导航控制器中使用无主参考的简单示例:

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)
    }
}

This means that RegisterViewController must be initialized than we can safely get self. 这意味着RegisterViewController必须初始化,而不是我们可以安全地获得自我。 navigationController and from here to get items count. navigationController并从这里获取项目数。 If you try to make it as [weak self], XCode will complain because self(viewcontroller) can be nil, so we must use unowned. 如果你试图把它变成[弱自我],XCode会抱怨因为self(viewcontroller)可以是nil,所以我们必须使用unowned。

Another example with UIBarButtonItem UIBarButtonItem的另一个例子

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

What we see here? 我们在这看到什么? See the target which stands for " The object that receives the action message. " which means that object that receives the action message can not be nil and must be initialized. 请参阅目标,该目标代表“ 接收操作消息的对象。 ”这意味着接收操作消息的对象不能为零并且必须初始化。

A very nice explanation from drewag in this article. 本文中来自drewag的一个非常好的解释

The only time where you really want to use [unowned self] or [weak self] is when you would create a strong reference cycle. 您真正想要使用[无主自我]或[弱自我]的唯一时间是您创建一个强大的参考周期。 A strong reference cycle is when there is a loop of ownership where objects end up owning each other (maybe through a third party) and therefore they will never be deallocated because they are both ensuring that each other stick around. 一个强大的参考周期是当存在一个所有权循环,其中对象最终彼此拥有(可能通过第三方),因此它们将永远不会被释放,因为它们都确保彼此坚持。

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

相关问题 我应该为Realm.write()使用[unown self]吗? - Should l I use [unowned self] for Realm.write()? 为什么我永远不想启用可测试性 - Why would I ever NOT want to Enable Testability 在此关闭过程中,我需要[无主的自我]还是[弱的自我]? - Do I need [unowned self] or [weak self] in this closure? 是否有必要在 UIView.animateWithDuration(...) 的闭包中使用 [unowned self]? - Is it necessary to use [unowned self] in closures of UIView.animateWithDuration(...)? 我是否需要AlamoFire中的[无主自我],或者它已被照顾? - Do I need [unowned self] in AlamoFire, or is it already taken care of? 可选关闭是否总是 escaping? 我们应该在上面使用[weak self]还是[unowned self]? - Is optional closure always escaping? Should we use [weak self] or [unowned self] on it? 为什么我要使用 CAAnimationGroup? - Why would I use an CAAnimationGroup? 为什么不能给一个无主常数一个初始值? - Why can't I give an unowned constant an initial value? RxSwift:当一个类有一个disposeBag属性时,总是使用[unowned self]是否安全? - RxSwift: Is it safe to always use [unowned self] when a class has a disposeBag property? 在后台获取上调用完整函数时,何时需要使用“ .noData”? - When would I ever need to use “.noData” when calling the complete function on background fetch?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM