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

如何用GCD并行执行Swift数组中图片URL的下载任务?

如何在Swift中并行下载多张图片并等待全部完成?

没问题,我来帮你搞定这个并行下载的需求!不用修改你的URL数组,借助GCD的DispatchGroup就能轻松实现并行执行+等待全部完成的逻辑,下面直接上方案:

基础实现(假设downloadImage(_:)是同步方法)

let urls:[String] = [
    "http://acme.com/one.jpeg",
    "http://acme.com/two.jpeg",
    "http://acme.com/three.jpeg",
]

// 创建调度组,用来跟踪所有异步任务的完成状态
let downloadGroup = DispatchGroup()

for url in urls {
    // 每启动一个任务前,标记"进入组"
    downloadGroup.enter()
    
    // 在全局并发队列执行下载任务,自动实现并行
    DispatchQueue.global().async {
        defer {
            // 用defer确保任务无论成功/失败,最终都会标记"离开组"
            downloadGroup.leave()
        }
        downloadImage(url)
    }
}

// 等待所有任务完成后,在指定队列执行后续操作(这里用主队列,适合后续更新UI)
downloadGroup.notify(queue: DispatchQueue.main) {
    print("all images downloaded.")
}

关键逻辑拆解

  • DispatchGroup的核心机制:enter()和leave()必须成对出现,调度组会统计未完成的任务数量,当数量归0时就会触发后续的notify回调。
  • 全局并发队列的作用:DispatchQueue.global()是系统维护的线程池,会自动把不同的下载任务分配到不同线程执行,天然实现并行效果。
  • notify方法的意义:它不会阻塞当前线程,而是在所有任务完成后,在你指定的队列(比如主队列)执行闭包,保证打印语句只会在全部下载完成后触发。

如果downloadImage(_:)是异步方法(带Completion Handler)

如果你的downloadImage本身是异步实现的(比如用URLSession做网络请求),只需要把leave()放到下载的完成回调里就行,示例如下:

先定义异步版的downloadImage

func downloadImage(_ urlString: String, completion: @escaping () -> Void) {
    guard let url = URL(string: urlString) else {
        completion()
        return
    }
    
    URLSession.shared.dataTask(with: url) { data, response, error in
        // 这里处理下载后的逻辑:比如保存图片、处理错误等
        if let data = data {
            // 示例:保存图片到临时目录
            try? data.write(to: URL(fileURLWithPath: "/tmp/\(url.lastPathComponent)"))
        }
        
        // 下载完成后调用completion
        completion()
    }.resume()
}

对应的并行执行代码

let urls:[String] = [
    "http://acme.com/one.jpeg",
    "http://acme.com/two.jpeg",
    "http://acme.com/three.jpeg",
]

let downloadGroup = DispatchGroup()

for url in urls {
    downloadGroup.enter()
    
    // 直接调用异步方法即可,URLSession本身会在后台队列执行
    downloadImage(url) {
        downloadGroup.leave()
    }
}

downloadGroup.notify(queue: DispatchQueue.main) {
    print("all images downloaded.")
}

这样就能完美实现所有图片的并行下载,并且确保所有任务完成后才打印提示信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:28:24