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

Swift中基于async/await的图片并行下载优化方案咨询

基于async/await的Swift并行图片下载改进方案

你的原代码通过for循环逐个await图片下载任务,导致所有请求串行执行,效率较低。以下是基于Swift async/await的并行改进方案,核心是利用withTaskGroup实现批量任务并行处理。

基础并行版本(不保证顺序)

这个版本会并行发起所有图片下载请求,任务完成后按完成顺序收集结果:

extension ImageDownloader {
    func download() async -> [Image] {
        let list = await fetchList()
        
        return await withTaskGroup(of: Image.self) { group in
            // 为每个图片下载任务创建子任务,并行执行
            for item in list {
                group.addTask {
                    print(item.imageName)
                    return await self.fetch(imageName: item.imageName)
                }
            }
            
            // 遍历任务组,收集所有完成的结果
            var images = [Image]()
            for await image in group {
                images.append(image)
            }
            
            return images
        }
    }
}

保持原列表顺序的并行版本

如果需要返回的图片数组顺序和原列表一致,可以给每个任务绑定索引,收集结果时对应到原位置:

extension ImageDownloader {
    func download() async -> [Image] {
        let list = await fetchList()
        let imageCount = list.count
        // 初始化对应容量的数组,用于按索引存储结果
        var images = [Image?](repeating: nil, count: imageCount)
        
        return await withTaskGroup(of: (index: Int, image: Image).self) { group in
            // 为每个列表项创建带索引的下载任务
            for (index, item) in list.enumerated() {
                group.addTask {
                    print(item.imageName)
                    let image = await self.fetch(imageName: item.imageName)
                    return (index, image)
                }
            }
            
            // 按索引将结果放入对应位置
            for await (index, image) in group {
                images[index] = image
            }
            
            // 转换为非可选的Image数组
            return images.compactMap { $0 }
        }
    }
}

带并发数限制的版本

如果列表过长,一次性发起大量请求可能导致服务器压力过大或触发限流,可添加最大并发数限制:

extension ImageDownloader {
    // 默认限制最大并发数为4,可根据需求调整
    func download(maxConcurrent: Int = 4) async -> [Image] {
        let list = await fetchList()
        let imageCount = list.count
        var images = [Image?](repeating: nil, count: imageCount)
        var currentIndex = 0
        
        return await withTaskGroup(of: (index: Int, image: Image).self) { group in
            // 先启动一批任务,数量不超过最大并发数和列表总数
            for _ in 0..<min(maxConcurrent, imageCount) {
                guard currentIndex < imageCount else { break }
                let taskIndex = currentIndex
                group.addTask {
                    let image = await self.fetch(imageName: list[taskIndex].imageName)
                    return (taskIndex, image)
                }
                currentIndex += 1
            }
            
            // 每当一个任务完成,立即启动下一个任务,维持最大并发数
            for await (taskIndex, image) in group {
                images[taskIndex] = image
                if currentIndex < imageCount {
                    let nextIndex = currentIndex
                    group.addTask {
                        let nextImage = await self.fetch(imageName: list[nextIndex].imageName)
                        return (nextIndex, nextImage)
                    }
                    currentIndex += 1
                }
            }
            
            return images.compactMap { $0 }
        }
    }
}

关键说明

  • withTaskGroup是Swift async/await体系中处理批量并行任务的标准API,系统会自动管理任务的调度和资源分配。
  • 并行任务的执行顺序由系统和网络情况决定,若需保持原列表顺序,必须通过索引绑定的方式处理。
  • 限制并发数是网络请求的最佳实践,可避免因请求过载导致的性能问题或服务端限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 03:43:12