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

Swift中如何通过DispatchGroup等待异步函数的Completion Block完成?

解决DispatchGroup等待异步Completion Block的问题

我明白你的困惑啦——原来的写法里,DispatchQueue.async(group:)只会等到你传入的外层闭包执行完毕(也就是调用完getDataFromUrl就结束了),但getDataFromUrl内部是异步的URLSession.dataTask,它的completion block要等网络请求完成才会执行,所以你的group.notify会提前触发,根本没等到两个网络请求真正完成。

核心解决思路:手动管理DispatchGroup的enter()和leave()

我们不能依赖async(group:)的自动分组管理,而是要手动标记异步任务的开始和结束:

  • 在发起每个异步任务前调用group.enter(),让DispatchGroup的任务计数+1
  • 在getDataFromUrl的completion block里调用group.leave(),让任务计数-1
  • 当计数回到0时,group.notify的闭包才会执行,确保两个网络请求都完成

修改后的完整代码示例

let queue = DispatchQueue(label: "com.company.app.queue", attributes: .concurrent)
let group = DispatchGroup()

// 第一个异步任务(func1)
group.enter() // 标记任务启动
queue.async {
    // 替换成你的实际URL
    let url1 = URL(string: "https://example.com/data1")!
    getDataFromUrl(url: url1) { data, response, error in
        // 这里处理func1的结果,比如解析数据、错误处理
        if let error = error {
            print("Func1 failed: \(error.localizedDescription)")
        } else if let data = data {
            print("Func1 got data: \(data.count) bytes")
        }
        
        group.leave() // 标记任务完成
    }
}

// 第二个异步任务(func2)
group.enter()
queue.async {
    let url2 = URL(string: "https://example.com/data2")!
    getDataFromUrl(url: url2) { data, response, error in
        // 处理func2的结果
        if let error = error {
            print("Func2 failed: \(error.localizedDescription)")
        } else if let data = data {
            print("Func2 got data: \(data.count) bytes")
        }
        
        group.leave()
    }
}

// 等待所有任务完成后执行后续逻辑
group.notify(queue: DispatchQueue.main) { // 通常用主队列做UI更新,也可以用你自己的queue
    print("#3 finished")
}

关键注意事项

  • 必须保证enter()和leave()一一对应:如果少写了leave(),DispatchGroup的计数永远不会回到0,notify永远不会触发;如果多写了leave(),会导致计数负数,程序可能崩溃。
  • group.leave()是线程安全的:不管getDataFromUrl的completion block在哪个队列执行,直接调用leave()就行,不需要额外切换队列。
  • 如果需要在completion里更新UI,记得在completion内部切换到主队列(比如DispatchQueue.main.async { ... }),这和DispatchGroup的同步逻辑是分开的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:41:18