You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 20:35:24