在2014年WWDC会议403中,有以下幻灯片

演讲者说,在那种情况下,如果我们不在那里使用[u主self],就会发生内存泄漏。这是否意味着我们应该总是在闭包中使用[ucontrolled self] ?

在Swift Weather应用程序的ViewController.swift的第64行,我没有使用[u主self]。但是我通过使用一些@ iboutlet来更新UI,比如self。温度和自加载指示器。这可能没问题,因为我定义的所有@IBOutlets都是弱的。但是为了安全起见,我们应该总是使用[无主的自我]吗?

class TempNotifier {
  var onChange: (Int) -> Void = {_ in }
  var currentTemp = 72
  init() {
    onChange = { [unowned self] temp in
      self.currentTemp = temp
    }
  }
}

当前回答

根据Apple-doc

弱引用总是可选类型,并且是自动的 当它们引用的实例被释放时变为nil。 如果捕获的引用永远不会变成nil,那么它应该始终被捕获为无主引用,而不是弱引用

的例子,

    // if my response can nil use  [weak self]
      resource.request().onComplete { [weak self] response in
      guard let strongSelf = self else {
        return
      }
      let model = strongSelf.updateModel(response)
      strongSelf.updateUI(model)
     }

    // Only use [unowned self] unowned if guarantees that response never nil  
      resource.request().onComplete { [unowned self] response in
      let model = self.updateModel(response)
      self.updateUI(model)
     }

其他回答

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let controller = storyboard.instantiateViewController(withIdentifier: "AnotherViewController")
        self.navigationController?.pushViewController(controller, animated: true)

    }

}



import UIKit
class AnotherViewController: UIViewController {

    var name : String!

    deinit {
        print("Deint AnotherViewController")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        print(CFGetRetainCount(self))

        /*
            When you test please comment out or vice versa

         */

//        // Should not use unowned here. Because unowned is used where not deallocated. or gurranted object alive. If you immediate click back button app will crash here. Though there will no retain cycles
//        clouser(string: "") { [unowned self] (boolValue)  in
//            self.name = "some"
//        }
//


//
//        // There will be a retain cycle. because viewcontroller has a strong refference to this clouser and as well as clouser (self.name) has a strong refferennce to the viewcontroller. Deint AnotherViewController will not print
//        clouser(string: "") { (boolValue)  in
//            self.name = "some"
//        }
//
//


//        // no retain cycle here. because viewcontroller has a strong refference to this clouser. But clouser (self.name) has a weak refferennce to the viewcontroller. Deint AnotherViewController will  print. As we forcefully made viewcontroller weak so its now optional type. migh be nil. and we added a ? (self?)
//
//        clouser(string: "") { [weak self] (boolValue)  in
//            self?.name = "some"
//        }


        // no retain cycle here. because viewcontroller has a strong refference to this clouser. But clouser nos refference to the viewcontroller. Deint AnotherViewController will  print. As we forcefully made viewcontroller weak so its now optional type. migh be nil. and we added a ? (self?)

        clouser(string: "") {  (boolValue)  in
            print("some")
            print(CFGetRetainCount(self))

        }

    }


    func clouser(string: String, completion: @escaping (Bool) -> ()) {
        // some heavy task
        DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
            completion(true)
        }

    }

}

如果你不确定[无主自我],那么使用[弱自我]

以下是来自苹果开发者论坛的精彩语录:

无主vs无主(安全)vs无主(不安全)

unowned(safe) is a non-owning reference that asserts on access that the object is still alive. It's sort of like a weak optional reference that's implicitly unwrapped with x! every time it's accessed. unowned(unsafe) is like __unsafe_unretained in ARC—it's a non-owning reference, but there's no runtime check that the object is still alive on access, so dangling references will reach into garbage memory. unowned is always a synonym for unowned(safe) currently, but the intent is that it will be optimized to unowned(unsafe) in -Ofast builds when runtime checks are disabled.

无主vs弱

unowned actually uses a much simpler implementation than weak. Native Swift objects carry two reference counts, and unowned references bump the unowned reference count instead of the strong reference count. The object is deinitialized when its strong reference count reaches zero, but it isn't actually deallocated until the unowned reference count also hits zero. This causes the memory to be held onto slightly longer when there are unowned references, but that isn't usually a problem when unowned is used because the related objects should have near-equal lifetimes anyway, and it's much simpler and lower-overhead than the side-table based implementation used for zeroing weak references.

更新:在现代Swift中,weak内部使用与un物主相同的机制。所以这个比较是不正确的,因为它比较了Objective-C的弱和Swift的unonwed。

原因

What is the purpose of keeping the memory alive after owning references reach 0? What happens if code attempts to do something with the object using an unowned reference after it is deinitialized? The memory is kept alive so that its retain counts are still available. This way, when someone attempts to retain a strong reference to the unowned object, the runtime can check that the strong reference count is greater than zero in order to ensure that it is safe to retain the object. What happens to owning or unowned references held by the object? Is their lifetime decoupled from the object when it is deinitialized or is their memory also retained until the object is deallocated after the last unowned reference is released? All resources owned by the object are released as soon as the object's last strong reference is released, and its deinit is run. Unowned references only keep the memory alive—aside from the header with the reference counts, its contents is junk.

兴奋,是吗?

unowned is similar to weak they don't a retained object from being destroyed, but weak variables turned to nil when the object its a reference to no longer exists, which we can handle with the normal checking of nils, unowned will just become garbage, you can't tell they are no longer garbage and using them will crash. The problem with weak is if an object has references to it by weak variables, when its destroyed, it has to go through every reference to it and set that variable to nil, this clearly is going to be expensive, using unowned instead is going just crash and finding this kind of bug is going to be difficult. One place to use unowned is if you are creating some carefully contained datatype, which has a clear interface, and its internals are not directly accessible, for you implementation it may be useful to have lots of circular references but that are self contained, you can used unowned references to let you break those circular references, with out the expense of weak variables, for example you may have a node tree, and each node needs has to have a reference to its parent, deleting a node is going to delete all its children, so there is no point of all the children having to have all there parent references set to nil.

根据Apple-doc

弱引用总是可选类型,并且是自动的 当它们引用的实例被释放时变为nil。 如果捕获的引用永远不会变成nil,那么它应该始终被捕获为无主引用,而不是弱引用

的例子,

    // if my response can nil use  [weak self]
      resource.request().onComplete { [weak self] response in
      guard let strongSelf = self else {
        return
      }
      let model = strongSelf.updateModel(response)
      strongSelf.updateUI(model)
     }

    // Only use [unowned self] unowned if guarantees that response never nil  
      resource.request().onComplete { [unowned self] response in
      let model = self.updateModel(response)
      self.updateUI(model)
     }

更新11/2016

我写了一篇关于扩展这个答案的文章(通过研究SIL来理解ARC做了什么),请在这里查看。

原来的答案

前面的答案并没有给出什么时候使用一种而不是另一种的直接规则,所以让我补充一些东西。

无主或弱的讨论归结为变量和引用它的闭包的生命周期问题。

场景

你可以有两个可能的场景:

The closure have the same lifetime of the variable, so the closure will be reachable only until the variable is reachable. The variable and the closure have the same lifetime. In this case you should declare the reference as unowned. A common example is the [unowned self] used in many example of small closures that do something in the context of their parent and that not being referenced anywhere else do not outlive their parents. The closure lifetime is independent from the one of the variable, the closure could still be referenced when the variable is not reachable anymore. In this case you should declare the reference as weak and verify it's not nil before using it (don't force unwrap). A common example of this is the [weak delegate] you can see in some examples of closure referencing a completely unrelated (lifetime-wise) delegate object.

实际使用

那么,大多数时候你会/应该使用哪种呢?

引用乔·格罗夫在推特上的话:

无主更快,并且允许不可变性和非可选性。 如果你不需要弱,就不要用它。

你会在这里找到更多关于无主内部工作的信息。

*通常也称为无主(safe),表示在访问无主引用之前执行运行时检查(导致无效引用崩溃)。