Swift中能否对同步返回值的函数使用async/await语法?
结论
同时带有@escaping异步完成回调、又有同步返回值的函数,完全可以适配async/await语法,只是编译器无法为这类函数自动生成桥接版本,需要手动用Continuation实现封装逻辑。
注:你示例中写的func test async -> Int存在语法错误,Swift中async修饰符需要放在参数列表与返回箭头之间,正确写法为func test() async -> Int。
适配方法
这类函数常见于旧版本的异步API设计:通常同步返回值是任务ID、请求句柄这类用于任务管控的即时值,异步回调则用来传递任务最终的执行结果。你可以根据自身业务需求,选择对应的封装方式:
- 如果你需要同时用到同步返回的句柄、以及异步回调的结果,可以将async函数的返回值定义为元组,同时承载两类值:
// 原函数示例 func test(_ completion: @escaping (Int) -> Void) -> Int { // 同步生成任务ID并立即返回 let taskId = 2024001 // 模拟异步任务执行 DispatchQueue.global().asyncAfter(deadline: .now() + 2) { completion(88) } return taskId } // async/await封装版本 func test() async -> (taskId: Int, result: Int) { var taskId: Int! let result = await withCheckedContinuation { continuation in // 调用原函数时直接拿到同步返回的任务ID taskId = test { asyncValue in // 回调触发时恢复异步执行流程,传递异步结果 continuation.resume(returning: asyncValue) } } return (taskId, result) }
- 如果你不需要用到同步返回的句柄(比如不需要拿任务ID做取消、查询操作),可以直接丢弃同步返回值,仅封装异步结果:
func test() async -> Int { await withCheckedContinuation { continuation in // 同步返回值直接舍弃 _ = test { result in continuation.resume(returning: result) } } }
注意事项
- 必须保证
continuation.resume在所有路径上仅被调用一次:如果原函数的回调存在多次触发的可能,需要加状态位做拦截,重复resume会直接触发运行时崩溃。 - 不要尝试给这类函数加编译器自动桥接标记(如
@asyncHandler),自动桥接逻辑默认函数无同步返回值,强行使用会丢失同步返回内容,甚至触发编译错误。 - 如果原函数的回调可能抛出错误,将
withCheckedContinuation替换为withThrowingCheckedContinuation即可匹配错误抛出逻辑。
内容的提问来源于stack exchange,提问作者Dannis Case
相关产品推荐
相关产品推荐

