defer with Errors and Early Returns
Ensure cleanup even when throwing or returning early.
defer with Errors and Early Returns is a free Swift Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
defer Runs on return
A defer block runs even when the function exits early via return.
func check(_ value: Int) {
defer { print("cleanup ran") }
if value < 0 {
print("negative, returning early")
return
}
print("value is", value)
}
check(-5)Cleanup on Every Path
No matter which return fires, the deferred cleanup runs exactly once.
func classify(_ n: Int) {
defer { print("done classifying") }
if n == 0 { print("zero"); return }
if n > 0 { print("positive"); return }
print("negative")
}
classify(0)defer Runs on throw
When a function throws, registered defers still run as the scope unwinds.
enum MyError: Error { case bad }
func risky(_ fail: Bool) throws {
defer { print("cleanup on the way out") }
if fail { throw MyError.bad }
print("no failure")
}
try? risky(true)Combining return and throw
Whether the function returns normally or throws, the same defer fires.
enum E: Error { case oops }
func op(_ flag: Bool) throws -> Int {
defer { print("op finishing") }
if flag { throw E.oops }
return 42
}
let r = try? op(false)
print(r ?? -1)Cleanup Before Error Propagates
The defer runs before the thrown error reaches the caller, so resources are released first.
enum E: Error { case fail }
func load(_ broken: Bool) throws {
print("open")
defer { print("close") }
if broken { throw E.fail }
print("read")
}
do {
try load(true)
} catch {
print("caught:", error)
}Guard With defer
A common pattern: acquire, defer cleanup, then guard with early returns that still trigger cleanup.
func process(_ items: [Int]) {
print("start")
defer { print("finished") }
guard !items.isEmpty else {
print("nothing to do")
return
}
print("processing", items.count, "items")
}
process([])defer and Throwing Loops
A defer inside a loop runs at each iteration end, even if a later statement throws.
enum E: Error { case stop }
func loop() throws {
for i in 1...3 {
defer { print("end", i) }
if i == 2 { throw E.stop }
print("body", i)
}
}
try? loop()Order With Early Return
Multiple defers still run in LIFO order on an early return.
func multi(_ skip: Bool) {
defer { print("A") }
defer { print("B") }
if skip { return }
print("body")
}
multi(true)Logging on Failure
Use defer to log completion or failure consistently across all exit paths.
enum E: Error { case bad }
func attempt(_ fail: Bool) throws {
var success = false
defer { print("attempt success:", success) }
if fail { throw E.bad }
success = true
}
try? attempt(true)Restoring State on throw
defer is ideal for rolling back temporary state when an operation throws.
enum E: Error { case fail }
func transaction(_ fail: Bool) throws {
var inProgress = true
defer { inProgress = false; print("inProgress:", inProgress) }
if fail { throw E.fail }
print("committed")
}
try? transaction(true)Best Practice
Rely on defer for cleanup that must survive early returns and thrown errors, so no exit path leaks resources.
enum E: Error { case x }
func safe(_ fail: Bool) throws {
print("acquire")
defer { print("release") }
if fail { throw E.x }
print("use")
}
try? safe(true)Quick Check
Test defer with errors and returns.
Recap
defer runs on every scope exit, including early return and a thrown error, executing before the error propagates. This makes it the reliable place for cleanup and state restoration across all exit paths, with LIFO ordering preserved.
func f(_ skip: Bool) {
defer { print("cleanup") }
if skip { return }
print("work")
}
f(true)Frequently asked questions
Is the “defer with Errors and Early Returns” lesson free?
Yes — the full text of “defer with Errors and Early Returns” is free to read here on the web, and the Swift Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Swift Academy course, upgrade to CoddyKit PRO.
What will I learn in “defer with Errors and Early Returns”?
Ensure cleanup even when throwing or returning early. 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; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “defer with Errors and Early Returns” 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
- How defer Works
- Multiple defer Blocks Ordering
- defer for Resource Cleanup
- defer with Errors and Early Returns