3.9 · Weak collections, nested closures, structs holding references, weak let and escaped pointers
Real code stores references in collections, closures and structs, and each shape has a lifetime rule that is easy to get subtly wrong.
Mental model. For every reference you store, ask who owns it, who just observes it, and what keeps the observer from outliving the owner.
Storing references
Weak collections, nested closure captures and what copying a struct costs.
- How do you hold a collection of objects without owning them: WeakBox arrays, NSHashTable and NSMapTable?
Swift collections hold strong references, so an observer list or a registry of views keeps everything alive. Three ways to hold weakly: an array of wrapper… - A closure captures [weak self] and promotes it with guard let. Can a closure created inside it still keep self alive?
Yes. [weak self] protects only the closure it is written on. Inside it, guard let self creates a strong local self, and any closure you create inside that… - What does copying a struct that holds class references cost, and how do you see it?
A struct copy is a bitwise copy plus one retain per stored reference (including those nested inside other fields and the buffer of an array or string). In the…
Corner cases
weak let and unowned optionals, and pointers that outlive their storage.
- Can a reference be weak let, or unowned and optional, and what does each do when the target dies?
Both are allowed in current Swift. weak let (a weak constant) works since Swift 5.10: the reference is set once in init, can never be reassigned, but still… - Why must a pointer obtained from an array or withUnsafe… never be stored, and how do you catch a dangling one?
Passing arr to an UnsafePointer<Int> parameter, or calling withUnsafeBufferPointer, gives you the address of the array’s current buffer, valid only for the…
More in Memory, ARC & runtime
- 3.1 · ARC, autorelease pools, object lifetime
- 3.2 · strong, weak, unowned, unowned(unsafe)
- 3.3 · Cycles: delegates, closures, timers, Combine, tasks
- 3.4 · Object layout, side tables, tagged pointers
- 3.5 · The copy-on-write mechanism
- 3.6 · Retain traffic, parameter conventions, Unmanaged, bridging
- 3.7 · Leaks, abandoned memory, footprint, and the tools
- 3.8 · deinit rules, process exit, isolated deinit, noncopyable types and consume
- 3.10 · Enum layout, existential boxing, tail allocation, slice retention, growth and the command-line tools