函数在处理另一函数的completionHandler前就返回结果,该如何修复?
Swift逃逸闭包回调无法同步返回值的解决方案
你遇到的问题根源是带@escaping逃逸闭包的函数是异步执行的,闭包的执行时机晚于外层函数的return语句,因此不可能通过常规return语句同步拿到闭包内的计算结果。另外你原有代码中resultString用let声明为常量,无法在闭包内修改,属于编译级错误,以下方案已统一修正该问题。
方案1:回调传值(兼容所有系统版本)
这是最通用的异步逻辑写法,无需依赖高版本系统特性,将后续需要使用返回值的逻辑放到回调闭包内执行即可:
// 改造getResult为带回调的异步函数 func getResult(x: Int, y: Int, completion: @escaping (String) -> Void) { summ(x: x, y: y) { result in let resultString = "Result: \(result)" completion(resultString) } } // 调用示例 getResult(x: 15, y: 10) { resultString in // 所有需要用到resultString的后续逻辑都写在这里 print(resultString) // 输出:Result: 25 }
方案2:async/await异步返回(Swift 5.5+ 优先推荐)
如果你的项目部署目标为iOS 15+/macOS 12+及以上,可使用Swift原生async/await语法,写法更简洁,逻辑更清晰:
// 先把原有基于回调的summ函数封装为async版本 func summAsync(x: Int, y: Int) async -> Int { await withCheckedContinuation { continuation in summ(x: x, y: y) { result in continuation.resume(returning: result) } } } // getResult可以声明为async函数直接返回字符串 func getResult(x: Int, y: Int) async -> String { let result = await summAsync(x: x, y: y) return "Result: \(result)" } // 调用示例 Task { let resultString = await getResult(x: 15, y: 10) // 在这里执行后续逻辑 print(resultString) // 输出:Result: 25 }
方案3:信号量同步等待(不推荐,仅特殊场景使用)
如果必须同步拿到返回值,可使用信号量阻塞当前线程等待回调执行完成,注意:该方案会卡住调用线程,绝对不能在主线程调用,否则会导致UI无响应:
func getResult(x: Int, y: Int) -> String { var resultString = "" let semaphore = DispatchSemaphore(value: 0) summ(x: x, y: y) { result in resultString = "Result: \(result)" semaphore.signal() } semaphore.wait() return resultString } // 调用示例(只能在后台线程调用) DispatchQueue.global().async { let resultString = getResult(x: 15, y: 10) print(resultString) // 输出:Result: 25 }
内容的提问来源于stack exchange,提问作者Resly34
相关产品推荐
相关产品推荐

