When exactly is an object deallocated: at the end of its scope, or after its last use?
Predict first
In what order does this print?
final class Res {
deinit { print("deinit") }
}
func work() {
let r = Res()
withExtendedLifetime(r) { print("using") }
print("after")
}
work()
- using, after, deinit
- using, deinit, after
- deinit, using, after
Mental model. The library may take the book back the moment you finish reading it, not when you leave the building.
Neither is promised. The compiler is free to release an object after its last use, which can be earlier than the closing brace. Since Swift 5.7, lexical lifetimes keep a variable alive to the end of its scope across “deinit barriers” (calls that could observe the object going away), so ordinary code behaves as you expect. Pure computation on a value the optimiser can see may still shorten it.
This shows up as bugs that only appear in release builds: a helper kept in a local let is released while its asynchronous work is still pending, or a [weak self] closure sees nil sooner than expected. Keep ownership explicit: store the object in a property, or use withExtendedLifetime(x) { … } when it genuinely must outlive a region. Never rely on deinit timing for correctness.
withExtendedLifetime pins r until its closure ends, and the local still lives until work() returns.
Common traps
- Keeping a helper in a local variable and expecting it to live until its callback. Nothing keeps it alive once you stop using it.
- Putting essential cleanup ordering in
deinit. The exact moment is the compiler’s choice.
They might follow up with
- Which build shows the difference? Optimised builds shorten lifetimes most; Debug builds keep objects to the end of scope.
- What does
withExtendedLifetimedo? It guarantees the object stays alive until the closure returns.
Related questions
- 3.1.1 How does ARC work, and how is it different from garbage collection?
- 3.2.3 How do you decide between weak, unowned and strong for a back-reference?
← What is a reference count, and how do you check that you hold the… What did manual reference counting look like, and which rules did ARC… →