iOS Swift异步/并发/并行执行任务及批量调用提速问询
嘿,这个问题问到点子上了——在Swift里搞定异步、并发、并行任务,是提升APP性能尤其是处理批量操作的核心技巧。我先给你理清楚这几个概念的区别,再直接给你解决那四个方法并行执行的具体方案。
在iOS Swift中实现异步/并发/并行任务
先搞清楚三个概念的区别
- 异步(Async):不用等当前任务执行完就能启动下一个,不会卡住当前线程(比如主线程不会被阻塞,APP不会假死)
- 并发(Concurrency):看起来多个任务“同时”进行,其实是CPU快速切换不同任务执行(单核CPU也能实现)
- 并行(Parallelism):真正的同时执行,需要多核CPU支持,多个任务在不同核心上跑
主流实现方案
方案1:Swift Concurrency(Async/Await,iOS 13+ 推荐)
这是苹果现在主推的异步编程方式,代码简洁、易读,错误处理也更优雅。针对你的四个批量任务,最直接的方式是用async let同时启动所有任务,然后等待全部完成:
第一步:确保你的方法是异步的
如果passingMsgIdsTofetchMsgss目前是带 completion handler的旧写法,先把它转成Async/Await版本:
// 假设原方法是这样的 func passingMsgIdsTofetchMsgss(messageIDs: [String], completion: @escaping ([Message]) -> Void) { // 这里是耗时操作,比如网络请求或者本地数据库查询 } // 转成Async/Await版本 func passingMsgIdsTofetchMsgss(messageIDs: [String]) async -> [Message] { return await withCheckedContinuation { continuation in self.passingMsgIdsTofetchMsgss(messageIDs: messageIDs) { messages in continuation.resume(returning: messages) } } }
第二步:并行执行所有批量任务
用async let同时启动四个任务,它们会在后台并发执行,最后用await等待所有任务完成:
func fetchAllMessages() async { do { // 同时启动四个异步任务 async let batch1Result = self.passingMsgIdsTofetchMsgss(messageIDs: msgIDBatches[0]) async let batch2Result = self.passingMsgIdsTofetchMsgss(messageIDs: msgIDBatches[1]) async let batch3Result = self.passingMsgIdsTofetchMsgss(messageIDs: msgIDBatches[2]) async let batch4Result = self.passingMsgIdsTofetchMsgss(messageIDs: msgIDBatches[3]) // 等待所有任务完成,拿到所有结果 let allResults = await [batch1Result, batch2Result, batch3Result, batch4Result] // 这里可以处理合并后的结果,比如把所有消息合并成一个数组 let allMessages = allResults.flatMap { $0 } print("所有消息加载完成,共\(allMessages.count)条") } catch { // 处理可能出现的错误(如果你的异步方法抛出错误的话) print("加载消息失败:\(error.localizedDescription)") } }
如果需要更灵活的控制(比如动态添加任务、提前取消等),可以用TaskGroup:
func fetchAllMessagesWithTaskGroup() async throws -> [Message] { return try await withThrowingTaskGroup(of: [Message].self) { group in // 遍历所有批次,添加任务到group for batch in msgIDBatches { group.addTask { return await self.passingMsgIdsTofetchMsgss(messageIDs: batch) } } // 收集所有结果 var allMessages: [Message] = [] for try await messages in group { allMessages.append(contentsOf: messages) } return allMessages } }
方案2:GCD(Grand Central Dispatch,兼容iOS 13以下)
如果你的APP需要支持iOS 13之前的版本,就用GCD的DispatchGroup来实现并发执行:
func fetchAllMessagesWithGCD() { let dispatchGroup = DispatchGroup() // 用全局队列执行耗时任务,选择合适的QoS(用户发起的任务用.userInitiated) let workQueue = DispatchQueue.global(qos: .userInitiated) // 用串行队列保证结果写入的线程安全,避免数据竞争 let resultQueue = DispatchQueue(label: "com.yourapp.messageResultQueue") var allResults: [[Message]] = [] // 遍历每个批次,添加任务到队列 for batch in msgIDBatches { dispatchGroup.enter() workQueue.async { [weak self] in guard let self = self else { dispatchGroup.leave() return } self.passingMsgIdsTofetchMsgss(messageIDs: batch) { messages in resultQueue.async { allResults.append(messages) } dispatchGroup.leave() } } } // 所有任务完成后的回调 dispatchGroup.notify(queue: DispatchQueue.main) { let allMessages = allResults.flatMap { $0 } print("所有消息加载完成,共\(allMessages.count)条") // 这里可以更新UI或者处理业务逻辑 } }
注意事项
- 线程安全:如果你的
passingMsgIdsTofetchMsgss方法会修改共享变量(比如全局数组),一定要用串行队列或者锁来保护,避免数据竞争导致的崩溃或错误 - QoS选择:根据任务类型选择合适的服务质量等级,比如用户触发的任务用
.userInitiated,后台同步任务用.background,系统会根据QoS分配CPU资源 - 错误处理:不管用哪种方案,都要处理任务可能出现的失败情况(比如网络错误、数据库异常),避免APP崩溃
- 取消任务:如果用户在任务执行过程中退出页面,记得取消正在执行的任务,避免资源浪费(Swift Concurrency里用
Task.cancel(),GCD里用DispatchWorkItem的cancel()方法)
内容的提问来源于stack exchange,提问作者user9364391
相关产品推荐
相关产品推荐

