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.