SwiftUI中如何用Async/Await替代检查变量处理异步调用
改用Async-Await重构SwiftUI异步逻辑
以下是用async-await替代原check变量计数方案的重构代码,同时保留所有原有业务逻辑:
首先,定义自定义错误类型来统一处理远程请求的错误:
enum RemoteError: Error, LocalizedError { case fatalError(String) var errorDescription: String? { switch self { case .fatalError(let message): return message } } }
然后,将原有的同步请求方法封装为异步函数,处理错误检查:
// 获取远程主分支 private func fetchRemoteHead(url: String) async throws -> String { // 用Task.detached将同步阻塞操作放在后台线程执行 return try await Task.detached(priority: .background) { let branch = try Remote().getRemoteHEAD(url: url) guard !branch[0].contains("fatal:") else { throw RemoteError.fatalError("Error: getRemoteHead") } return branch[0] }.value } // 获取远程分支列表 private func fetchRemoteBranches(url: String) async throws -> [String] { return try await Task.detached(priority: .background) { let branches = try Remote().getRemoteBranch(url: url) guard !branches[0].contains("fatal:") else { throw RemoteError.fatalError("Error: getRemoteBranch") } return branches }.value }
最后,替换原.onAppear中的逻辑为async-await实现:
.task { do { // 并行启动两个异步任务,无需手动计数等待 async let mainBranchResult = fetchRemoteHead(url: repoUrlStr) async let branchesResult = fetchRemoteBranches(url: repoUrlStr) // 等待两个任务全部完成 let (mainBranch, branches) = try await (mainBranchResult, branchesResult) // 在主线程更新UI,确保线程安全 await MainActor.run { self.mainBranch = mainBranch self.selectedBranch = mainBranch self.arrayBranch = branches self.activeSheet = .select // 保留原有的UI强制更新逻辑 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { self.allBranches.toggle() } } } catch let error as RemoteError { // 处理自定义的远程请求错误 await MainActor.run { Log.warning(error.localizedDescription) self.activeSheet = .error(error.localizedDescription) } } catch { // 处理其他未知错误 await MainActor.run { Log.error("Failed to fetch remote data: \(error.localizedDescription)") self.activeSheet = .error("Failed to fetch remote data") } } }
重构关键点说明:
- 替代手动计数:用
async let实现两个任务并行执行,通过try await一次性等待所有任务完成,彻底移除check变量,逻辑更直观。 - SwiftUI原生异步支持:使用
.task修饰符替代DispatchQueue,自动绑定视图生命周期,视图消失时会自动取消任务,避免内存泄漏。 - 统一错误处理:将原有的字符串错误检查转换为自定义错误类型,通过
do-catch集中处理所有错误场景,代码更健壮。 - 线程安全:所有UI更新操作通过
MainActor.run确保在主线程执行,符合SwiftUI的线程安全要求。 - 后台执行同步操作:用
Task.detached将原同步阻塞的Remote方法放在后台线程执行,避免阻塞主线程导致UI卡顿。
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

