defer runs cleanup code when execution leaves the current scope.

Close work in one place

shouldFail
defer_cleanup.swift
Replay: real traced execution (multi-file project)
func processTask(_ shouldFail: Bool) -> String {
    var steps: [String] = []
    steps.append("open")

    defer {
        steps.append("close")
        print(steps.joined(separator: ">"))
    }

    if shouldFail {
        steps.append("fail")
        return "failed"
    }

    steps.append("work")
    return "done"
}

let shouldFail = false
let outcome = processTask(shouldFail)

print(outcome)
func processTask(_ shouldFail: Bool) -> String {
    var steps: [String] = []
    steps.append("open")

    defer {
        steps.append("close")
        print(steps.joined(separator: ">"))
    }

    if shouldFail {
        steps.append("fail")
        return "failed"
    }

    steps.append("work")
    return "done"
}

let shouldFail = true
let outcome = processTask(shouldFail)

print(outcome)
  1. shouldFail ← false

    19let shouldFail→ false = false  //@shouldFail=true20let outcome = processTask(shouldFailfalse)
  2. steps ← []

    1func processTask(_ shouldFailfalse: Bool) -> String {2    var steps→ []: [String] = []3    steps→ ["open"].append("open")45    defer {6        steps.append("close")7        print(steps.joined(separator: ">"))8    }910    if shouldFail {11        steps.append("fail")12        return "failed"13    }1415    steps→ ["open", "work"].append("work")16    return "done"17}
  3. steps ← ["open", "work", "close"], outcome ← done

    5    defer {6        steps→ ["open", "work", "close"].append("close")7        print(steps["open", "work", "close"].joined(separator: ">"))8    }910    if shouldFail {11        steps.append("fail")12        return "failed"13    }1415    steps.append("work")16    return "done"17}1819let shouldFail = false  //@shouldFail=true20let outcome→ done = processTask(shouldFailfalse)2122print(outcomedone)
    outputopen>work>close
    done
  1. shouldFail ← true

    19let shouldFail→ true = true20let outcome = processTask(shouldFailtrue)
  2. steps ← []

    1func processTask(_ shouldFailtrue: Bool) -> String {2    var steps→ []: [String] = []3    steps→ ["open"].append("open")
  3. steps ← ["open", "fail", "close"]

    5defer {6    steps→ ["open", "fail", "close"].append("close")7    print(steps["open", "fail", "close"].joined(separator: ">"))8}910if shouldFailtrue {11    steps["open"].append("fail")12    return "failed"13}
    outputopen>fail>close
  4. outcome ← failed

    19let shouldFail = true20let outcome→ failed = processTask(shouldFailtrue)2122print(outcomefailed)
    outputfailed
defer A deferred block keeps cleanup near setup while still running after the main work path finishes.