Making Old Async Code Work with Swift's New Async/Await Feature
A continuation in Swift is a bridge that lets you use older async code easily with the new async/await feature. You do this using withCheckedContinuation and withCheckedThrowingContinuation functions to make the old code fit smoothly into new async workflows.
Here’s a basic example of how you might use withCheckedContinuation in a scenario where you have an asynchronous function that fetches data from a network resource but does not support async/await:
Recommended by LinkedIn
// Example of a non-async function
func fetchData(completion: @escaping (Data?, Error?) -> Void) {
DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
let data = "Example data".data(using: .utf8) // Simulated data
completion(data, nil)
}
}
// Using withCheckedContinuation to wrap the fetchData call
func fetchDataAsync() async throws -> Data {
try await withCheckedThrowingContinuation { continuation in
fetchData { data, error in
if let error = error {
continuation.resume(throwing: error)
} else if let data = data {
continuation.resume(returning: data)
} else {
continuation.resume(throwing: NSError(domain: "DataError", code: 0, userInfo: nil))
}
}
}
}
// Async function to call fetchDataAsync
func exampleUsage() async {
do {
let data = try await fetchDataAsync()
print("Fetched data: \(data)")
} catch {
print("An error occurred: \(error)")
}
}
// Run the async function
Task {
await exampleUsage()
}
In this example - The fetchData function simulates an asynchronous network call using a completion handler.
- The fetchDataAsync function then wraps this call in a withCheckedThrowingContinuation to allow it to be used with Swift's async/await pattern.
- The exampleUsage function demonstrates how you would call fetchDataAsync asynchronously and handle any potential errors.