Memory & ARC cheat sheet
The 7 Memory & ARC interview answers in 30 seconds each, plus quick facts. Printable, free.
One page per topic: print it or save it as PDF from your browser's print menu. Practise these questions
How ARC works
ARC counts the strong references to each class instance. The compiler inserts retain and release calls; when the count reaches zero, deinit runs and the memory is freed immediately. It is deterministic, unlike garbage collection, but it can't free objects that reference each other strongly, which is a retain cycle.
Retain cycles and how to break them
A retain cycle happens when two or more objects hold strong references to each other, so their counts never reach zero and they leak. Break it by making one direction weak or unowned, usually the back-reference: delegates, parent pointers and closures that capture their owner.
Retain cycles in closures
A closure captures self strongly by default. If the object stores that closure (directly, or through something it owns), the object keeps the closure alive and the closure keeps the object alive. Capture [weak self] and unwrap with guard let self, or capture only the values you need.
weak vs unowned
Both avoid increasing the strong count. weak is optional and becomes nil when the object is freed, so it is always safe; use it when the other object can disappear first, like delegates. unowned is non-optional and assumes the object outlives the reference; accessing it after deallocation crashes. Use unowned only when lifetimes are guaranteed.
Autorelease pools today
Some Objective-C APIs return autoreleased objects that are freed only when the current autorelease pool drains, usually at the end of a run-loop turn. In a tight loop creating many such objects, such as images or Foundation strings, memory spikes until the loop ends. Wrapping the loop body in autoreleasepool { } frees them each iteration.
Finding memory leaks
Start with Xcode's Memory Graph debugger: open and close a screen a few times, pause, and look for instances that should be gone; it shows the retain path keeping them alive. Use the Leaks and Allocations instruments for growth over time, and Address and Thread Sanitizers for memory corruption and data races.
Responding to memory pressure
Keep memory low before the warning comes: downsample images to their display size, cache decoded images in NSCache with a cost limit, and free caches on didReceiveMemoryWarning or when the app goes to the background. The system kills apps that use too much memory, especially in the background.
Quick facts
- unowned(unsafe)
- Like unowned but without the runtime check, so access after deallocation is undefined behaviour. Almost never needed.
- weak references
- Always optional vars that ARC sets to nil when the object is freed.
- Timer retain
- A scheduled Timer is retained by the run loop and retains its target; invalidate it, or use the block API with [weak self].
- withExtendedLifetime
- Keeps an object alive until the closure ends, when the optimizer might otherwise free it early.