What if your app could clean up after itself perfectly without you lifting a finger?
Why Weak self and unowned self patterns in Swift? - Purpose & Use Cases
Imagine you write a Swift app where two objects keep strong references to each other, like two friends holding hands tightly. When you try to clean up one friend, they both stay stuck together forever, causing your app to use more memory and slow down.
Without using weak or unowned references, your objects create a strong cycle. This means they never get released from memory, leading to memory leaks. Your app becomes slow and crashes eventually because it runs out of memory.
Using weak and unowned references breaks this strong hold between objects. It lets one object hold a lighter grip, so when no one else needs it, it can be cleaned up safely. This keeps your app fast and healthy.
class A { var b: B? } class B { var a: A? } // Both hold strong references causing a cycle
class A { var b: B? } class B { weak var a: A? } // Weak reference breaks the cycle
This pattern enables your app to manage memory smartly, preventing leaks and crashes by avoiding strong reference cycles.
Think of a parent and child relationship in your app. The parent owns the child strongly, but the child only holds a weak reference back to the parent. When the parent is gone, the child can be cleaned up too, keeping memory tidy.
Strong reference cycles cause memory leaks.
Weak and unowned references break these cycles.
Using them keeps your app efficient and crash-free.
Practice
weak self inside a closure in Swift?Solution
Step 1: Understand strong reference cycles
Strong reference cycles happen when closures captureselfstrongly, causing memory leaks.Step 2: Role of
Usingweak selfweak selfmakes the reference toselfoptional and allows it to become nil, breaking the cycle.Final Answer:
To prevent strong reference cycles and allowselfto become nil -> Option CQuick Check:
Weak self avoids memory leaks = A [OK]
- Thinking weak self guarantees non-nil self
- Confusing weak with unowned self
- Assuming weak self copies self
self as unowned in a Swift closure?Solution
Step 1: Recall capture list syntax
Swift uses square brackets with capture specifiers beforeinin closures.Step 2: Correct unowned syntax
The correct syntax is[unowned self] into captureselfas unowned.Final Answer:
[unowned self] in -> Option BQuick Check:
Unowned capture syntax = [unowned self] in [OK]
- Swapping order like [self unowned]
- Missing brackets or 'in' keyword
- Using weak instead of unowned when asked
class Example {
var closure: (() -> Void)?
func setup() {
closure = { [weak self] in
print(self == nil ? "nil" : "not nil")
}
}
}
let example = Example()
example.setup()
example.closure?()
What will be printed when example.closure?() is called?Solution
Step 1: Analyze weak self capture
The closure capturesselfweakly, so inside the closureselfis optional.Step 2: Check
Theselflifetimeexampleinstance is still alive whenclosure?()is called, soselfis not nil.Final Answer:
not nil -> Option AQuick Check:
Weak self is alive here = not nil [OK]
- Assuming weak self is always nil
- Confusing weak self with unowned self
- Expecting runtime crash due to optional
class Person {
var name = "Alice"
lazy var greet: () -> Void = {
print("Hello, \(self.name)!")
}
}
let p = Person()
p.greet()
Solution
Step 1: Detect strong reference cycle risk
The closure capturesselfstrongly, andgreetis lazy var, so cycle possible.Step 2: Choose unowned self for non-optional self
Sinceselfwill always exist whengreetis called,unowned selfis safe and avoids optional unwrapping.Final Answer:
Use [unowned self] in closure to avoid strong reference cycle -> Option AQuick Check:
Unowned self for guaranteed self = C [OK]
- Ignoring strong reference cycles
- Using weak self and forcing unwrap unnecessarily
- Thinking no problem exists
Solution
Step 1: Understand lifetime of self and closure
Ifselfwill definitely exist while closure runs,unowned selfis safe and avoids optionals.Step 2: Compare weak vs unowned for this case
weak selfrequires optional unwrapping, butunowned selfassumesselfexists, simplifying code and avoiding leaks.Final Answer:
Useunowned selfbecauseselfwill outlive the closure, avoiding optionals -> Option DQuick Check:
Unowned self for guaranteed lifetime = A [OK]
- Using weak self but not unwrapping safely
- Using strong self causing memory leaks
- Ignoring self capture causing leaks
Ready to prove it?
Pass the test and this pattern moves unknown
