Retain cycles & breaking with weak/unowned
Spot retain cycles between objects and closures, then break them using weak and unowned references safely.
Retain cycles & breaking with weak/unowned is a free Swift Academy lesson on CoddyKit. This is lesson 2 of 3. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, and your progress syncs across the web and the CoddyKit app. The Swift Academy course includes 3 lessons in total.
What is a retain cycle?
A retain cycle happens when objects (or closures) keep strong references to each other so ARC never reaches zero. Break cycles with weak or unowned.
Object ↔ object cycle
Two strong references in both directions create a leak: neither object can drop to zero.
final class Owner {
var gadget: Gadget?
deinit { print("Owner deinit") }
}
final class Gadget {
var owner: Owner?
deinit { print("Gadget deinit") }
}
// Strong ⇄ strong (cycle)
var o: Owner? = Owner()
var g: Gadget? = Gadget()
o!.gadget = g
g!.owner = o
o = nil // no deinit
g = nil // still no deinit (leak)Break with weak
Make one side weak (often the back-reference like delegate/owner) to allow ARC to release both.
final class Owner2 {
var gadget: Gadget2?
deinit { print("Owner2 deinit") }
}
final class Gadget2 {
weak var owner: Owner2? // weak breaks cycle; becomes nil automatically
deinit { print("Gadget2 deinit") }
}
var o2: Owner2? = Owner2()
var g2: Gadget2? = Gadget2()
o2!.gadget = g2
g2!.owner = o2
o2 = nil // Owner2 deinit
g2 = nil // Gadget2 deinitClosure cycle (strong self)
Closures capture variables strongly by default. If the object also owns the closure, that forms a cycle.
final class TimerClient {
var tick: (() -> Void)?
deinit { print("TimerClient deinit") }
func start() {
// BAD: closure strongly captures self; self keeps tick strongly
tick = {
print("tick from", self) // strong capture of self
}
}
}
var c: TimerClient? = TimerClient()
c!.start()
c = nil // no deinit — closure holds self stronglyBreak with capture lists
Use [weak self] (optional) for safe cleanup; use [unowned self] only if self is guaranteed alive when the closure executes.
final class TimerClient2 {
var tick: (() -> Void)?
deinit { print("TimerClient2 deinit") }
func start() {
// Use [weak self] when self can go away before tick runs
tick = { [weak self] in
guard let self = self else { return } // safe unwrap
print("tick from", self)
}
// Alternative when lifetime is guaranteed: [unowned self]
// tick = { [unowned self] in print("tick from", self) }
}
}
var c2: TimerClient2? = TimerClient2()
c2!.start()
c2 = nil // deinit now prints — no cycleChecklist
Checklist:
- Two-way references? Make one side weak (e.g., delegate).
- Closures stored on a type? Capture [weak self] and unwrap safely.
- Use [unowned self] only when lifetime is guaranteed; otherwise it can crash.
Weak vs unowned in closures
Quick check: Which capture list is safer when the object may be released?
Recap
Recap: Identify cycles in objects and closures. Break them with weak or unowned appropriately; prefer weak when in doubt.
Learn Swift with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 122
- Lessons
- 409
Frequently Asked Questions
Is the “Retain cycles & breaking with weak/unowned” lesson free?
Yes — any 3 lessons of the Swift Academy learning path, including “Retain cycles & breaking with weak/unowned”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Swift Academy course includes 3 lessons in total.
What will I learn in “Retain cycles & breaking with weak/unowned”?
Spot retain cycles between objects and closures, then break them using weak and unowned references safely. You practise Swift Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Swift Academy?
No prior experience is required. Swift Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 2 of 3.
How long does the “Retain cycles & breaking with weak/unowned” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Swift Academy lesson?
Yes. Every Swift Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- ARC basics: strong / weak / unowned
- Retain cycles & breaking with weak/unowned
- Value types to reduce sharing