0
0
Swiftprogramming~10 mins

Escaping closures (@escaping) in Swift - Step-by-Step Execution

Choose your learning style9 modes available
Concept Flow - Escaping closures (@escaping)
Define function with closure parameter
Is closure marked @escaping?
Closure can escape
Store closure
Function returns
Closure called later
This flow shows how a closure marked @escaping can be stored and called after the function returns, while non-escaping closures run immediately inside the function.
Execution Sample
Swift
var completionHandlers: [() -> Void] = []

func doAsyncTask(completion: @escaping () -> Void) {
    completionHandlers.append(completion)
}

doAsyncTask {
    print("Task done")
}
This code stores an escaping closure in an array to be called later, simulating an asynchronous task.
Execution Table
StepActionState of completionHandlersOutput
1Define empty array completionHandlers[]
2Call doAsyncTask with closure[]
3Inside doAsyncTask, append closure to completionHandlers[closure]
4doAsyncTask returns[closure]
5Closure not called yet[closure]
6Call closure from completionHandlers[0][closure]Task done
💡 Execution stops after closure is called and prints output.
Variable Tracker
VariableStartAfter Step 3After Step 6
completionHandlers[][closure][closure]
Key Moments - 3 Insights
Why do we need @escaping for the closure parameter?
Because the closure is stored in completionHandlers and called after the function returns, it escapes the function scope. The execution_table row 3 shows the closure being appended and stored.
What happens if we don't mark the closure as @escaping?
The compiler will give an error because the closure is used after the function returns, which is not allowed for non-escaping closures. This is implied by the flow in concept_flow.
When is the closure actually executed?
The closure is executed later when we call completionHandlers[0]() as shown in execution_table step 6.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the state of completionHandlers after step 3?
AIt is still empty
BIt contains two closures
CIt contains one closure
DIt is nil
💡 Hint
Check the 'State of completionHandlers' column at step 3 in execution_table.
At which step does the closure actually print 'Task done'?
AStep 4
BStep 6
CStep 2
DStep 1
💡 Hint
Look at the 'Output' column in execution_table to find when 'Task done' is printed.
If the closure parameter was not marked @escaping, what would happen?
AThe compiler would give an error
BThe closure would run twice
CThe closure could still be stored and called later
DThe closure would run immediately
💡 Hint
Refer to key_moments question about the need for @escaping.
Concept Snapshot
Escaping closures (@escaping):
- Mark closure parameters with @escaping if stored or called after function returns.
- Non-escaping closures run immediately inside the function.
- Escaping closures can be stored and called later.
- Compiler enforces @escaping to avoid unsafe use.
- Use @escaping for async callbacks or delayed execution.
Full Transcript
This visual execution trace shows how escaping closures work in Swift. We start with an empty array to store closures. When we call a function with an @escaping closure parameter, the closure is appended to the array and the function returns. The closure is not executed immediately but stored for later use. Later, when we call the closure from the array, it runs and prints output. The key point is that @escaping allows the closure to live beyond the function call. Without @escaping, the compiler would prevent storing the closure. This trace helps beginners see step-by-step how escaping closures behave.