Question 4
Memory management — ARC, strong, weak, unowned
Explain ARC’s role in Swift. When do you use weak vs unowned references, and how do you break retain cycles in closures and delegates?
Answer outline
ARC counts strong references to heap-allocated class instances; when the count hits zero, deinit runs. Structs are not ARC-managed as whole values, but nested class references inside structs still participate in ARC.
weak is optional and becomes nil when the object is deallocated. Use it for delegates and closure captures where the referenced object may be released before the reference is used.
unowned is non-optional and assumes the referent outlives the reference — access after deallocation crashes. Only use it when the lifetime relationship is guaranteed.
Closures capture strongly by default. Use [weak self] or [unowned self]; capture lists appear before the closure’s parameter list.
Principles
- Prefer
weakoverunowned—unownedcrashes if the referent is deallocated while still referenced. - Delegate properties must be
weak; a strong delegate creates a retain cycle. - Escaping closures capture
selfstrongly — add[weak self]whenever the closure may outlive its owner. - Timers, notification observers, and network callbacks are classic retain cycle sources.
protocol DetailDelegate: AnyObject {
func onDone()
}
final class DetailVC {
weak var delegate: DetailDelegate?
}
fetch { [weak self] result in
guard let self else { return }
self.apply(result)
}
Follow-up angles
@MainActordoes not remove ARC concerns—escaping closures still needweakself where cycles are possible.