Bird
Raised Fist0
Swiftprogramming~20 mins

Escaping closures (@escaping) in Swift - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Escaping Closure Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
Output of a function with an escaping closure
What will be printed when this Swift code runs?
Swift
func performTask(completion: @escaping () -> Void) {
    DispatchQueue.global().async {
        print("Task started")
        completion()
    }
}

performTask {
    print("Task completed")
}

print("Function called")
AFunction called\nTask started\nTask completed
BTask started\nTask completed\nFunction called
CFunction called\nTask completed\nTask started
DTask completed\nTask started\nFunction called
Attempts:
2 left
💡 Hint
Think about how async code runs in the background and when the print statements execute.
🧠 Conceptual
intermediate
1:30remaining
Why use @escaping in Swift closures?
Which statement best explains why the @escaping attribute is required for a closure parameter in Swift?
ABecause the closure is called after the function returns, so it escapes the function's scope.
BBecause the closure modifies variables outside its own scope.
CBecause the closure is guaranteed to run synchronously within the function.
DBecause the closure is optional and might not be called.
Attempts:
2 left
💡 Hint
Think about when the closure is executed relative to the function call.
🔧 Debug
advanced
2:00remaining
Identify the error with closure escaping
What error will this Swift code produce and why?
Swift
func fetchData(completion: () -> Void) {
    DispatchQueue.global().async {
        completion()
    }
}

fetchData {
    print("Data fetched")
}
ANo error, prints 'Data fetched' asynchronously
BError: Missing return statement in closure
CRuntime crash due to closure escaping
DError: Closure use of non-escaping parameter 'completion' may allow it to escape
Attempts:
2 left
💡 Hint
Check the closure parameter declaration and how it's used inside an async block.
📝 Syntax
advanced
1:30remaining
Correct syntax for an escaping closure parameter
Which option correctly declares a function with an escaping closure parameter in Swift?
Afunc loadData(completion: escaping () -> Void) {}
Bfunc loadData(@escaping completion: () -> Void) {}
Cfunc loadData(completion: @escaping () -> Void) {}
Dfunc loadData(completion: () -> Void @escaping) {}
Attempts:
2 left
💡 Hint
Remember the position of @escaping in the parameter declaration.
🚀 Application
expert
2:30remaining
Determine the final value after escaping closure modifies a variable
What is the value of 'counter' after this Swift code runs?
Swift
var counter = 0

func incrementLater(completion: @escaping () -> Void) {
    DispatchQueue.global().async {
        counter += 1
        completion()
    }
}

incrementLater {
    print("Increment done")
}

// Wait briefly to let async code finish
Thread.sleep(forTimeInterval: 0.1)

print(counter)
A0
B1
C2
DCompilation error
Attempts:
2 left
💡 Hint
Consider that the increment happens asynchronously and the main thread waits before printing.

Practice

(1/5)
1. What does the @escaping keyword indicate in Swift closures?
easy
A. The closure can be called after the function returns
B. The closure is executed immediately within the function
C. The closure cannot capture variables from the surrounding scope
D. The closure is only used for synchronous tasks

Solution

  1. Step 1: Understand closure execution timing

    Closures without @escaping run inside the function before it returns.
  2. Step 2: Role of @escaping

    Marking a closure @escaping means it can be stored and called later, after the function ends.
  3. Final Answer:

    The closure can be called after the function returns -> Option A
  4. Quick Check:

    @escaping means delayed closure call [OK]
Hint: Escaping closures run later, not immediately [OK]
Common Mistakes:
  • Thinking @escaping closures run immediately
  • Confusing @escaping with synchronous execution
  • Believing @escaping closures cannot capture variables
2. Which of the following is the correct syntax to declare a function parameter as an escaping closure in Swift?
easy
A. func fetchData(completion: () -> Void) {}
B. func fetchData(completion: escaping () -> Void) {}
C. func fetchData(@escaping completion: () -> Void) {}
D. func fetchData(completion: @escaping () -> Void) {}

Solution

  1. Step 1: Identify correct placement of @escaping

    The @escaping keyword must appear before the closure type in the parameter list.
  2. Step 2: Check each option's syntax

    func fetchData(completion: @escaping () -> Void) {} correctly places @escaping before the closure type. Options A, C, and D have incorrect syntax.
  3. Final Answer:

    func fetchData(completion: @escaping () -> Void) {} -> Option D
  4. Quick Check:

    Correct syntax = func fetchData(completion: @escaping () -> Void) {} [OK]
Hint: Put @escaping before the closure type in parameters [OK]
Common Mistakes:
  • Placing @escaping before parameter name
  • Omitting @escaping for delayed closures
  • Writing 'escaping' without @ symbol
3. What will be the output of the following Swift code?
func performTask(completion: @escaping () -> Void) {
    DispatchQueue.main.async {
        completion()
    }
    print("Task started")
}

performTask {
    print("Task completed")
}
medium
A. Task started
B. Task completed\nTask started
C. Task started\nTask completed
D. Task completed

Solution

  1. Step 1: Understand async dispatch behavior

    The closure passed to DispatchQueue.main.async runs later, after the current function finishes.
  2. Step 2: Trace print statements order

    "Task started" prints immediately. Then the closure runs and prints "Task completed".
  3. Final Answer:

    Task started\nTask completed -> Option C
  4. Quick Check:

    Async closure runs after print [OK]
Hint: Async closures run after current code finishes [OK]
Common Mistakes:
  • Assuming closure runs before print
  • Ignoring async dispatch delay
  • Confusing order of print statements
4. Identify the error in this Swift function using an escaping closure:
func saveData(completion: () -> Void) {
    DispatchQueue.global().async {
        // Save operation
        completion()
    }
}
medium
A. Missing @escaping before closure parameter
B. Closure parameter should be optional
C. DispatchQueue.global() cannot be used here
D. Completion closure must return a value

Solution

  1. Step 1: Analyze closure usage inside async block

    The closure is called asynchronously after the function returns, so it must be marked @escaping.
  2. Step 2: Check function parameter declaration

    The parameter lacks @escaping, causing a compile error.
  3. Final Answer:

    Missing @escaping before closure parameter -> Option A
  4. Quick Check:

    Async closure needs @escaping [OK]
Hint: Async closure parameters must be @escaping [OK]
Common Mistakes:
  • Forgetting @escaping for async closures
  • Assuming closure is synchronous by default
  • Adding unnecessary optional to closure
5. You want to store a closure to call later after a network request finishes. Which is the correct way to declare and use this escaping closure in Swift?
class NetworkManager {
    var completionHandler: (() -> Void)?

    func requestData(completion: ???) {
        self.completionHandler = completion
        // Simulate network delay
        DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
            self.completionHandler?()
        }
    }
}
hard
A. completion: () -> Void
B. completion: @escaping () -> Void
C. completion: @autoclosure () -> Void
D. completion: @escaping @autoclosure () -> Void

Solution

  1. Step 1: Understand closure storage and delayed call

    The closure is saved in a property and called later asynchronously, so it must be @escaping.
  2. Step 2: Evaluate options for closure parameter

    Only completion: @escaping () -> Void correctly marks the closure as @escaping. Options A, B, and D are incorrect or unnecessary here.
  3. Final Answer:

    completion: @escaping () -> Void -> Option B
  4. Quick Check:

    Stored closures must be @escaping [OK]
Hint: Store closures? Use @escaping keyword [OK]
Common Mistakes:
  • Omitting @escaping when storing closures
  • Using @autoclosure unnecessarily
  • Marking closure without @escaping for delayed call
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard