如何基于多个独立异步函数的执行结果管理警告弹窗?
更优实现方案推荐
针对你这种并行执行两个独立任务、需要在任务完成后判断结果并弹窗的场景,推荐以下几种更可靠的实现方式,解决手动管理标记变量可能带来的线程安全和逻辑冗余问题:
方案一: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
相关产品推荐
相关产品推荐

