Swift Concurrency 中的 withCheckedThrowingContinuation

withCheckedThrowingContinuation 是 Swift Concurrency 中用于将基于回调的异步代码桥接到 async/await 模式的重要工具。让我详细介绍一下它的使用方法。

基本概念

withCheckedThrowingContinuation 用于将传统的回调式异步函数转换为 async/await 风格。它创建一个"续体"(continuation),让你能够在回调中恢复异步任务的执行。

函数签名

func withCheckedThrowingContinuation<T>(
    _ operation: (CheckedContinuation<T, Error>) -> Void
) async throws -> T

基本使用模式

func asyncVersion() async throws -> ReturnType {
    return try await withCheckedThrowingContinuation { continuation in
        callbackBasedFunction { result in
            // 在回调中处理结果并恢复续体
        }
    }
}

具体示例

1. 简单的网络请求

// 传统的回调式函数
func fetchData(completion: @escaping (Result<String, Error>) -> Void) {
    // 模拟网络请求
    DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
        completion(.success("Data loaded"))
    }
}

// 转换为 async/await 版本
func fetchData() async throws -> String {
    return try await withCheckedThrowingContinuation { continuation in
        fetchData { result in
            continuation.resume(with: result)
        }
    }
}

// 使用
func useFetchData() async {
    do {
        let data = try await fetchData()
        print("Received: \(data)")
    } catch {
        print("Error: \(error)")
    }
}

2. 文件读取示例

// 回调版本
func readFile(at path: String, completion: @escaping (Result<Data, Error>) -> Void) {
    DispatchQueue.global().async {
        do {
            let data = try Data(contentsOf: URL(fileURLWithPath: path))
            completion(.success(data))
        } catch {
            completion(.failure(error))
        }
    }
}

// async/await 版本
func readFile(at path: String) async throws -> Data {
    return try await withCheckedThrowingContinuation { continuation in
        readFile(at: path) { result in
            continuation.resume(with: result)
        }
    }
}

3. 你的工作目录示例分析

/// 获取当前工作目录(异步版本)
func getCurrentWorkingDirectory() async throws -> String {
    return try await withCheckedThrowingContinuation { continuation in
        // 调用原有的回调式函数
        getCurrentWorkingDirectoryAsync { result in
            // 在回调中将结果传递给续体
            continuation.resume(with: result)
        }
    }
}

重要注意事项

1. 续体必须被调用且只能调用一次

// ❌ 错误:可能不调用续体
func badExample() async throws -> String {
    return try await withCheckedThrowingContinuation { continuation in
        someAsyncFunction { result in
            if case .success = result {
                continuation.resume(with: result) // 只在成功时调用
            }
            // 错误:失败时没有调用续体!
        }
    }
}

// ✅ 正确:确保总是调用一次
func goodExample() async throws -> String {
    return try await withCheckedThrowingContinuation { continuation in
        someAsyncFunction { result in
            continuation.resume(with: result) // 总是调用
        }
    }
}

2. 处理取消

func cancellableOperation() async throws -> String {
    return try await withCheckedThrowingContinuation { continuation in
        let task = startSomeOperation { result in
            continuation.resume(with: result)
        }
        
        // 设置取消处理
        continuation.onCancel = {
            task.cancel()
        }
    }
}

3. 内存安全

续体不是线程安全的,确保在正确的上下文中使用:

// ❌ 错误:可能在后台线程调用
func unsafeExample() async throws -> String {
    return try await withCheckedThrowingContinuation { continuation in
        DispatchQueue.global().async {
            // 这可能导致问题
            continuation.resume(returning: "data")
        }
    }
}

// ✅ 正确:确保在适当的上下文中
func safeExample() async throws -> String {
    return try await withCheckedThrowingContinuation { continuation in
        someAsyncFunction { result in
            // 假设 someAsyncFunction 在正确的上下文中调用回调
            continuation.resume(with: result)
        }
    }
}

相关函数

  • withCheckedContinuation: 用于不会抛出错误的异步操作
  • withUnsafeThrowingContinuation: 不安全的版本,性能更好但需要手动管理内存
  • withCheckedContinuation: 安全的非抛出版本

实际应用场景

  1. 桥接旧代码: 将现有的回调式库转换为 async/await
  2. 第三方库集成: 当第三方库不支持 async/await 时
  3. 复杂异步操作: 需要将多个回调组合成一个 async 函数时

你的工作目录函数就是典型的应用场景:将基于回调的异步操作转换为更现代的 async/await 模式,使代码更简洁、更易读。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容