0
0
Swiftprogramming~10 mins

Weak self and unowned self patterns in Swift - Step-by-Step Execution

Choose your learning style9 modes available
Concept Flow - Weak self and unowned self patterns
Start Closure Capture
Capture self weakly or unowned
Closure Executes
Check if self exists (weak) or assume exists (unowned)
Use self
Closure Ends
This flow shows how closures capture self weakly or unowned, check self's existence, and safely use it or exit.
Execution Sample
Swift
class MyClass {
  var closure: (() -> Void)?
  var value = 10
  func setup() {
    closure = { [weak self] in
      print(self?.value ?? "No self")
    }
  }
}
This code sets up a closure capturing self weakly to avoid strong reference cycles.
Execution Table
StepActionself capturedself exists?OutputNotes
1Closure created with [weak self]weak reference to selfN/AN/AClosure holds weak self
2Closure called while self aliveweak reference to selfYes10self.value printed
3self deallocatedweak reference to selfNoNo selfself is nil, safe unwrap prints fallback
4Closure called after self deallocatedweak reference to selfNoNo selfNo crash, safe handling
5Closure created with [unowned self]unowned reference to selfN/AN/AClosure holds unowned self
6Closure called while self aliveunowned reference to selfYes10self.value printed
7self deallocatedunowned reference to selfNoCrashAccessing unowned self causes crash
8Closure called after self deallocatedunowned reference to selfNoCrashUnsafe access, program crashes
💡 Execution stops when closure finishes or program crashes due to unowned self access after deallocation
Variable Tracker
VariableStartAfter Step 2After Step 3After Step 6After Step 7
self (weak)Strong referenceExistsNilN/AN/A
self (unowned)Strong referenceExistsN/AExistsDeallocated (dangling)
Key Moments - 3 Insights
Why does using [weak self] not crash when self is nil?
Because weak self is an optional reference. The closure checks if self exists before using it (see step 3 and 4 in execution_table), so it safely handles nil without crashing.
Why does using [unowned self] crash after self is deallocated?
Unowned self is a non-optional reference that assumes self always exists. If self is deallocated (step 7 and 8), accessing unowned self causes a runtime crash because it points to invalid memory.
When should I use weak self vs unowned self in closures?
Use weak self when self might be nil during closure execution and you want to avoid crashes (safe optional). Use unowned self only when you are sure self will outlive the closure, avoiding optional unwrapping.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is printed when the closure with [weak self] is called after self is deallocated?
A"No self"
B10
CCrash
Dnil
💡 Hint
Check step 4 in the execution_table where self is nil and output is "No self"
At which step does accessing unowned self cause a crash?
AStep 6
BStep 7
CStep 3
DStep 2
💡 Hint
Look at the execution_table rows describing unowned self usage and crash at step 7
If we change [weak self] to [unowned self] in the closure, what happens when self is deallocated before closure call?
AClosure prints "No self" safely
BClosure does not run
CProgram crashes due to invalid self access
DClosure runs but self is nil
💡 Hint
Refer to variable_tracker and execution_table steps 7 and 8 for unowned self crash behavior
Concept Snapshot
Weak self and unowned self are ways closures capture self to avoid strong reference cycles.
Weak self is optional and safe if self might be nil.
Unowned self is non-optional and assumes self always exists.
Use weak self when self can be deallocated before closure runs.
Use unowned self only when self outlives the closure.
Accessing unowned self after deallocation causes a crash.
Full Transcript
This visual trace shows how closures capture self in Swift using weak and unowned references. When a closure captures self weakly, it holds an optional reference that can become nil if self is deallocated. The closure safely checks if self exists before using it, preventing crashes. When self is alive, the closure prints self's value. After self is deallocated, the closure prints a fallback message "No self" safely. In contrast, capturing self as unowned means the closure assumes self always exists. If self is deallocated before the closure runs, accessing unowned self causes a runtime crash because it points to invalid memory. This trace highlights when to use weak self (safe optional) versus unowned self (non-optional but unsafe if self is gone). Understanding these patterns helps avoid memory leaks and crashes in Swift closures.