Home > Net >  Could a guard let `self` = self inside a closure that uses [weak self] cause a crash if the object t
Could a guard let `self` = self inside a closure that uses [weak self] cause a crash if the object t

Time:06-27

I've looked at some comments to questions on stackoverflow about using [weak self] and [unowned self]. I need to be sure I understand correctly.

I am using the latest Xcode - Xcode 13.4, the latest macOS - macOS Monterey 12.4, and I'm writing code compatible with iOS 12.0 to the latest iOS 15.

First of all, am I correct that memory that has a strong reference to it is owned by whichever the strong reference belongs to?

Also, and this is what I really need to know, I want to know what happens if I use [weak self] in at the beginning of a closure, and then I have the statement guard let `self` = self else { return }. I believe the guard statement, if the condition succeeds, assigns the reference self holds to the newly declared strong reference named self in the let `self part of the guard statement. Is that correct?

What that leads me to ask is, What happens at the end of the closure. Am I correct that even though the newer self holds a strong reference, the memory the strong reference points to is deallocated once the code in the closure has executed the last statement in the closure, because the newer self with the strong reference is declared within the closure itself, and is deallocated along with all memory that had been allocated for that closure.

I think I got all of this right. If not, please let me know.

I am interested in any additional information or any clarifications if you will.

CodePudding user response:

If the closure holds a strong reference, it prevents the ARC to release the object as long as the closure is still accessible.

The weak and unowned self allow to resolve this strong ownership.
But this means that the object referenced by the closure's weak self could be deinitailized while the closure could still be called. In this case, the closure's self would refer to nil.

The guard would in fact just check that the reference is still valid. A nil would make it fail anyway. If it's a valid reference, it doesn't change the capture list; you could just assume that self will stay valid until the current execution of the closure returns.

CodePudding user response:

When you write a closure like this:

{ [weak self] in
    guard let self = self else { return }
    ...
}

You are checking that the class in which this closure is declared is still allocated, if that class is still allocated you are creating a new strong reference to it inside the closure itself.

You do that because if all other strong reference to the class are deleted there will still be the strong reference created in

guard let self = self else { return }

At that point you can be sure that until the end of the closure the class in which the closure is declared is allocated, because the reference is in the closure itself.

So, to answer your question, no, if you write

guard let self = self else { return }

that closure can't crash because you have a strong reference that's still alive.

Different thing is if you use [unowned self]. Unowned self is like an unwrapped optional. If you use it without checking its existence you are implicitly writing

self!.<something>

so if the self is deallocated when you call that closure it will crash.

  • Related