简体   繁体   中英

Strong, weak and unowned self in closures explanation

I need some explanation about references in closures in Swift. Here is my use case, let's imagine we have :

class A {...}
class B {

  func makeAclosure() {
   let instanceA = A()
   instanceA.someFunctionA(completion: {(input) in 
     self.someAnotherFunction(input)
   })
  }
}

Is there a retain cycle between class A and B or not ? In which case it can be a retain cycle in this kind of scenario ?

If your self object will potentially be deallocated before your closure is called, you should specify [weak self] , so that you can avoid bad access exceptions.

If you know that it will definitely not be deallocated, then you can use [unowned self] to create a reference that will behave like an implicitly unwrapped optional.

In your example, the instance of B owns the reference to instanceA (within the context of your makeAClosure() function), so you will not end up with a retain cycle.

You should consider the implementation of someFunctionA(completion:) , to determine if you need an unowned or a weak reference to self in that closure.


(A small aside: if you're using [weak self] , then to avoid having optionals such as self? throughout your code, you can use guard let `self` = self else { ... } to continue using self in the closure code.

It is not possible to say without looking at A.someFunctionA since it's unknown if completion is @escaping (eg if it's retained). For the rest of the answer I will assume that it is @escaping .

Swift needs to ensure runtime safety, and will keep any objects it might need in the future alive, in this case by making a strong reference to self (since self is the only variable used inside the closure).

In this scenario there is no reference cycle . This is because instanceA is not retained, so A => B, but B !=> A.

However, if instanceA was retained by B (let's say you create an instanceA: A property and set it) then you will have a retain cycle.

To get around this you can make variables within the closure either weak or unowned . They both do the same thing, but provide you with slightly different types. They both hold a weak reference, meaning that instanceA will not be increase the reference count of your B instance; if B is deallocated and there are no other reference, instanceA is also deallocated.

When using [weak self] self is optional , eg self: B? . However, [unowned self] is explicitly unwrapped, eg self: B! . This means that if the closure is called and self is nil your program will crash. This is why it's important to only use unowned when you know for certain that deallocating B will also deallocate A . There are a few scenarios where unowned is safe, eg the case when creating a closure and storing it on the same object that created it, but there are more nuances to this.

If unsure, use weak !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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