tezvyn:

Retain cycles and how to break them

AI-drafted, machine-checkedSource: interviewintermediate
WHAT IT TESTS

ARC and closure capture.

OUTLINE

a cycle is two objects (or a closure and its owner) holding mutual strong references so neither deallocates; break it with a [weak] or [unowned] capture list.

WHAT THIS TESTS It verifies you understand Automatic Reference Counting and can spot and break the closure-capture cycles that dominate real iOS memory bugs.

WHAT A RETAIN CYCLE IS ARC frees an object when its strong reference count hits zero. A retain cycle forms when objects, directly or through a closure, hold strong references to each other so neither count ever reaches zero. The memory is unreachable but never freed, a leak. The classic case is an object that stores a closure while that closure strongly captures the same object via self.

HOW TO RESOLVE IT Use a capture list to make the closure's capture of self non-strong. [weak self] makes self an Optional that becomes nil once the object deallocates, so you safely unwrap before use; choose it when the closure may outlive self or self may legitimately disappear. [unowned self] assumes self always outlives the closure and accesses it without optionality; choose it only when that lifetime guarantee truly holds, because a stale unowned access crashes.

COMMON WRONG ANSWERS Defaulting to unowned for convenience where the object can deallocate first, inviting crashes. Believing every closure leaks, when non-escaping closures and closures that do not capture self are fine. Adding [weak self] without then handling the nil case.

LIKELY FOLLOW-UPS When is unowned safe over weak? Do non-escaping closures cause cycles? How do delegates create cycles and why are they weak? How do you confirm the fix with the Memory Graph Debugger?

ONE CONCRETE EXAMPLE A class stores a completion handler: self.onDone = { self.update() }. Here self retains the closure and the closure retains self, so the object never deallocates. Rewriting it as self.onDone = { [weak self] in self?.update() } breaks the strong link; once nothing else holds the object it deallocates, the weak reference goes nil, and the update simply no-ops.

Read the original → docs.swift.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.