BeCuriouzBeCuriouz

Learn something new every day

📱 Mobile Programming
🔗

Why your iOS app leaks memory even with no garbage collector

💡 ARC frees an object when its strong reference count hits zero — so two objects strongly referencing each other leak forever unless you break the cycle with weak or unowned.

Swift has no garbage collector. Instead it uses ARC (Automatic Reference Counting): every class instance keeps a count of how many strong references point to it, and the moment that count hits zero, the object is deallocated. The compiler inserts the retain/release calls for you, so most of the time you never think about it — which is exactly why the classic bug is so easy to hit.

The trap is a strong reference cycle. If object A holds a strong reference to B, and B holds a strong reference back to A, then each keeps the other's count above zero — forever. Even after every other part of your app forgets about them, neither can be freed. That's a memory leak, no garbage collector required. It shows up constantly with closures: a closure captures self strongly while self also owns the closure.

The fix is to break one arrow in the cycle with a weak or unowned reference. A weak reference doesn't bump the count and automatically becomes nil when its target is deallocated (so it must be an Optional). An unowned reference also doesn't retain, but assumes the target always outlives it — accessing it after deallocation crashes. In closures you'll see this as a capture list: { [weak self] in ... }.

The reason delegate properties in UIKit are almost always declared weak is precisely this: a view controller owns its subviews strongly, so the subview pointing back at the controller as its delegate must be weak to avoid a cycle.

📚

Source: The Swift Programming Language — Automatic Reference Counting

🔗 Why your iOS app leaks memory even with no garbage collector — BeCuriouz