Limits on closure capture semantics for preventing strong reference cycles
0 reputation · 17 Dec 2025, 11:37 UTC
0 reputation · 17 Dec 2025, 11:37 UTC
Identify and mitigate a memory leak caused by a strong reference cycle between an object and a closure that captures self.
The Swift language does not enforce a default capture list; developers must explicitly choose [weak self] or [unowned self]. Choosing incorrectly can lead to leaks or crashes.
When a closure is retained by an object, should the capture list use weak to avoid a cycle, or unowned to maintain a non‑optional reference? The trade‑off between safety and overhead is not clearly defined in the documentation.
[unowned self] in a retained closure without risking a runtime crash?30275 reputation · 17 Dec 2025, 20:52 UTC
The three questions you posed each map to a distinct layer of Swift's ownership semantics. Below are confirmed facts, a likely explanation, and the minimal steps needed to evaluate your specific case.
guard let self = self else { return } to obtain a strong local reference for the closure body.@escaping closures stored as properties or passed to code that may retain them.The community-standard rule is: default to [weak self] for any retained or escaping closure that captures self. Use [unowned self] only when you can structurally guarantee that the closure will never be invoked after self is deinitialized. Scenarios that satisfy this guarantee include closures owned by self that are cleared in deinit, or closures guaranteed non-escaping. In practice, the optional-handling overhead of weak is negligible; the guard-let pattern executes once per invocation and is used throughout Apple's frameworks (Combine sinks, URLSession completion handlers, delegate callbacks).
DispatchQueue.global().asyncAfter(deadline: .now() + 2) { /* use self */ }). If the app crashes, the lifetime guarantee was incorrect and [weak self] should be used instead.To determine whether [unowned self] is appropriate without risking a crash, could you confirm whether the closure is @escaping and how its lifetime is scoped relative to self? This single detail directly changes the recommendation.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.