如何将Swift API调用重构为使用Swift 5.5 async/await语法?
重构后的完整实现
static func getBooks() async throws -> [Book]? { let request = getRequest(suffix: "books") // 替代原有dataTask回调API let (data, _) = try await URLSession.shared.data(for: request) // 解码失败直接抛出错误,可替代原有的强制崩溃逻辑 let books = try JSONDecoder().decode([Book].self, from: data) print("books.count: \(books.count)") return books }
如果需要保证返回结果自动回调到主线程,可给函数加上@MainActor标注:
@MainActor static func getBooks() async throws -> [Book]? { // 实现逻辑和上面一致 }
原有逻辑适配说明
URLSession.shared.dataTask替换:Foundation 从 iOS 15/macOS 12 开始提供原生 async/await 版本网络请求 APIdata(for:),会自动执行请求、返回数据/抛出错误,不需要手动调用resume(),也不需要手动处理回调内的error、data可选校验。DispatchQueue.main.async处理:async/await 环境下不需要手动切换主队列,如果你在 SwiftUI 视图中通过.task修饰符调用该方法,或者给函数加上@MainActor标注,返回结果后会自动执行在主线程。completion回调移除:async 函数直接通过返回值返回请求结果,错误通过throw抛出,不需要再传入回调闭包。如果需要保留原有遇到错误直接崩溃的逻辑,可以把代码中的try改为try!即可和原有表现一致。
调用方式示例
原有回调式调用:
YourClass.getBooks { books in // 处理返回的书籍数据 }
重构后的调用方式:
Task { do { let books = try await YourClass.getBooks() // 处理返回的书籍数据 } catch { // 统一处理请求、解码错误 print("请求失败:\(error)") } }
低版本系统兼容方案(iOS 13+/macOS 10.15+)
如果需要兼容低于 iOS 15 的系统,可通过withCheckedThrowingContinuation封装原有回调逻辑,不需要修改原有网络请求实现:
static func getBooks() async throws -> [Book]? { try await withCheckedThrowingContinuation { continuation in // 直接调用原有带completion的旧方法 getBooks { books in continuation.resume(returning: books) } } }
内容的提问来源于stack exchange,提问作者Edward J. Stembler
相关产品推荐
相关产品推荐

