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

iOS14下PHPickerViewController如何加载全部PHPickerResult获取选中图片数组

多选图片实现最佳实践

现有代码存在的问题

  • 异步回调执行顺序不固定,直接append会导致最终数组的顺序和用户选择顺序不一致
  • 完成条件判断错误:totalConversionsCompleted == index的逻辑完全不成立,最终需要匹配的是results.count而不是当前遍历的下标
  • 线程不安全:loadObject的回调默认在后台队列执行,多线程同时操作数组会出现数据竞争、计数错乱的问题

正确实现方案

采用DispatchGroup统一管理所有异步加载任务,预先创建固定长度的数组保证顺序,所有数组和计数操作都放在同一个串行队列(比如主队列)执行避免线程安全问题,这是官方推荐的标准实现方式。

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    picker.dismiss(animated: true)
    guard !results.isEmpty else { return }
    
    // 预先创建对应长度的数组,保证和用户选择顺序一致
    var images: [UIImage?] = Array(repeating: nil, count: results.count)
    let dispatchGroup = DispatchGroup()
    
    for (index, result) in results.enumerated() {
        guard result.itemProvider.canLoadObject(ofClass: UIImage.self) else { continue }
        dispatchGroup.enter()
        result.itemProvider.loadObject(ofClass: UIImage.self) { object, error in
            defer { dispatchGroup.leave() }
            let image = object as? UIImage
            // 所有数据操作切到主队列,保证线程安全
            DispatchQueue.main.async {
                images[index] = image
            }
        }
    }
    
    // 所有图片加载完成后统一回调
    dispatchGroup.notify(queue: .main) {
        // 可根据业务需求过滤掉加载失败的nil值
        let validImages = images.compactMap { $0 }
        // 此处处理拿到的图片数组即可
    }
}

可选优化点

  • 如果选中的图片数量多、体积大,建议增加加载状态提示,避免用户误以为界面卡住
  • 如果不需要保留加载失败的占位,可直接把成功加载的图片存入数组,无需提前占位
  • 如果存在大量图片加载需求,可以限制并行加载的数量,避免内存暴涨

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 10:21:02