These patterns help avoid memory problems when objects refer to each other. They keep your app running smoothly without crashes.
Weak self and unowned self patterns in Swift
someClosure = { [weak self] in
guard let self = self else { return }
// use self safely here
}
someClosure = { [unowned self] in
// use self directly here
}weak self creates a temporary, optional reference to self that can become nil.
unowned self creates a non-optional reference but assumes self will never be nil.
weak self to avoid a strong reference cycle. It safely unwraps self before use.class Example { var closure: (() -> Void)? func setup() { closure = { [weak self] in guard let self = self else { return } print("Using weak self safely") } } }
unowned self assuming self will always exist when the closure runs.class Example { var closure: (() -> Void)? func setup() { closure = { [unowned self] in print("Using unowned self directly") } } }
This program shows how weak self safely handles the case when the object is gone, while unowned self assumes the object is still there.
class Person { let name: String var greeting: (() -> Void)? init(name: String) { self.name = name } func greetWeak() { greeting = { [weak self] in guard let self = self else { print("Person no longer exists") return } print("Hello, my name is \(self.name) using weak self") } } func greetUnowned() { greeting = { [unowned self] in print("Hello, my name is \(self.name) using unowned self") } } } var person: Person? = Person(name: "Alice") person?.greetWeak() person?.greeting?() person = nil var person2: Person? = Person(name: "Bob") person2?.greetUnowned() person2?.greeting?() person2 = nil
Use weak self when self might become nil and you want to avoid crashes.
Use unowned self only when you are sure self will not be nil during closure execution.
Always test your code to avoid unexpected nil errors or memory leaks.
Weak self helps avoid memory leaks by allowing self to become nil inside closures.
Unowned self assumes self will always exist and avoids optional unwrapping.
Choosing the right pattern keeps your app safe and efficient.
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
