Skip to content

Swift async await

This article explains how to define async functions, how to call them, and how to convert callback functions into async functions when writing apps in Swift.

Basic Usage

await can only be called inside an async function or within a Task.

  1. Define an async function:
swift
func fetchImage() async {
  await loader.downloadImage()
}
  1. Use the async function:
swift
Button("Download with Async") {
  Task {
      await vm.fetchImage()
  }
}

Cancelling an Async Function

swift
var body: some View {
    VStack {
        if let image = vm.image {
            Image(uiImage: image)
        }
    }
    .onAppear {
        fetchImageTask = Task {
            await vm.fetchImage()
        }
    }
    .onDisappear {
        fetchImageTask?.cancel()
    }
}

Converting Callback Functions to Async Functions

You can use the withCheckedContinuation function to wrap a callback function (completion handler) into an async function.

swift
// Use withCheckedThrowingContinuation for throwing operations
// Use withCheckedContinuation for non-throwing operations
private func readImageData(item: PhotosPickerItem) async throws -> Data {
    return try await withCheckedThrowingContinuation { continuation in
        item.loadTransferable(type: Data.self) { result in
            switch result {
            case .success(let imageData):
                if let imageData {
                    continuation.resume(returning: imageData)
                } else {
                    continuation.resume(throwing: PickerError.noData)
                }
            case .failure(let error):
                continuation.resume(throwing: error)
            }
        }
    }
}