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

如何基于多个独立异步函数的执行结果管理警告弹窗?

更优实现方案推荐

针对你这种并行执行两个独立任务、需要在任务完成后判断结果并弹窗的场景,推荐以下几种更可靠的实现方式,解决手动管理标记变量可能带来的线程安全和逻辑冗余问题:

方案一:GCD DispatchGroup(最常用的轻量方案)

利用GCD的DispatchGroup可以自动跟踪多个异步任务的完成状态,无需手动维护completed标记,逻辑更简洁且线程安全:

// 存储两个任务的执行结果
var aTaskResult: Bool?
var bTaskResult: Bool?

let taskGroup = DispatchGroup()

// 异步执行任务a
taskGroup.enter()
DispatchQueue.global().async {
    aTaskResult = a()
    taskGroup.leave()
}

// 异步执行任务b
taskGroup.enter()
DispatchQueue.global().async {
    bTaskResult = b()
    taskGroup.leave()
}

// 监听所有任务完成,回到主队列处理UI
taskGroup.notify(queue: DispatchQueue.main) {
    // 任意一个任务失败就弹出警告
    if aTaskResult == false || bTaskResult == false {
        let alert = UIAlertController(title: "警告", message: "任务执行失败", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "确定", style: .default))
        self.present(alert, animated: true)
    }
}

优势:GCD原生支持,代码量少,自动处理任务完成的同步逻辑,避免手动判断标记的繁琐。

方案二:Combine响应式框架(iOS 13+ 推荐)

如果项目已经采用响应式编程,可以用Combine将同步函数包装为异步Publisher,通过合并操作统一处理结果:

import Combine

// 工具方法:把同步函数包装成异步Publisher
func wrapAsPublisher(_ function: @escaping () -> Bool) -> AnyPublisher<Bool, Never> {
    Future { promise in
        DispatchQueue.global().async {
            let result = function()
            promise(.success(result))
        }
    }.eraseToAnyPublisher()
}

// 包装两个任务为Publisher
let aPublisher = wrapAsPublisher(a)
let bPublisher = wrapAsPublisher(b)

// 合并两个Publisher,等待两者都完成后处理结果
var cancellables = Set<AnyCancellable>()
Publishers.Zip(aPublisher, bPublisher)
    .receive(on: DispatchQueue.main)
    .sink(receiveValue: { aResult, bResult in
        if !aResult || !bResult {
            let alert = UIAlertController(title: "警告", message: "任务执行失败", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "确定", style: .default))
            self.present(alert, animated: true)
        }
    })
    .store(in: &cancellables)

优势:响应式风格代码更简洁,自动管理异步流的生命周期,适合大型项目的统一状态管理。

方案三:OperationQueue(复杂任务场景)

如果需要更精细的任务控制(比如任务取消、优先级调整),可以用OperationQueue实现任务依赖:

let taskQueue = OperationQueue()
taskQueue.maxConcurrentOperationCount = 2 // 允许并行执行两个任务

var aTaskResult: Bool?
var bTaskResult: Bool?

// 创建任务a
let opA = BlockOperation {
    aTaskResult = a()
}

// 创建任务b
let opB = BlockOperation {
    bTaskResult = b()
}

// 创建完成后的UI任务
let completionOp = BlockOperation {
    DispatchQueue.main.async {
        if aTaskResult == false || bTaskResult == false {
            let alert = UIAlertController(title: "警告", message: "任务执行失败", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "确定", style: .default))
            self.present(alert, animated: true)
        }
    }
}

// 设置依赖:完成任务必须等a、b都执行完毕
completionOp.addDependency(opA)
completionOp.addDependency(opB)

// 添加任务到队列
taskQueue.addOperations([opA, opB], waitUntilFinished: false)
OperationQueue.main.addOperation(completionOp) // UI操作必须在主队列执行

优势:支持任务的取消、暂停、优先级设置,适合有复杂调度需求的场景。


内容的提问来源于stack exchange,提问作者Amit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 11:24:59