Understanding Swift's — withCheckedThrowingContinuation

Anas Poovalloor
2 min readJul 11, 2024

--

Swift’s withCheckedThrowingContinuation is a powerful function that bridges the gap between callback-based asynchronous code and modern async/await syntax. This post will explain its purpose, usage, and benefits.

What is it?

withCheckedThrowingContinuation is like a magical bridge between old-school callback-based code and modern async/await syntax. It helps you wrap callback-based functions so you can use them with async/await.

How does it work?

Imagine you have an old function that uses a callback:

func fetchData(completion: @escaping (Result<String, Error>) -> Void) {
// Some network call
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
completion(.success("Data fetched!"))
}
}

Now, let’s wrap it with withCheckedThrowingContinuation:

func fetchDataAsync() async throws -> String {
// Use withCheckedThrowingContinuation to bridge between callback and async code
try await withCheckedThrowingContinuation { continuation in
// Call the original callback-based fetchData function
fetchData { result in
// Handle the result of the fetchData call
switch result {
case .success(let data):
// If successful, resume the continuation with the fetched data
continuation.resume(returning: data)
case .failure(let error):
// If an error occurred, resume the continuation by throwing the error
continuation.resume(throwing: error)
}
}
}
}

Let’s break it down:

  1. We create a new async function fetchDataAsync().
  2. Inside, we use withCheckedThrowingContinuation.
  3. We call our old fetchData function.
  4. When the callback is called, we use continuation.resume to return the result or throw an error.

Now you can use it with async/await:

do {
let result = try await fetchDataAsync()
print(result) // "Data fetched!"
} catch {
print("Oops, an error occurred: \(error)")
}

Why is it “checked”?

The “checked” part means Swift will warn you if you forget to call continuation.resume. This helps prevent bugs where your async function might hang forever!

Your turn!

Try wrapping a callback-based function of your own using withCheckedThrowingContinuation. It's a great way to modernize old code and make it work seamlessly with async/await!

Conclusion

withCheckedThrowingContinuation is a valuable tool in your Swift development toolkit. It allows you to:

  1. Seamlessly integrate older, callback-based APIs with modern async/await code.
  2. Improve code readability and maintainability.
  3. Catch potential errors early with Swift’s built-in checks.

As you continue to develop in Swift, you’ll find this function invaluable for updating legacy code and working with libraries that haven’t yet adopted async/await syntax. Practice using it in your projects to become more comfortable with asynchronous programming patterns in Swift.

Ready to level up your Swift skills? Don’t miss Understanding Swift’s Async/Await.

--

--