PHPickerViewController未遵循图片选择顺序问题求助
问题
我们的代码最低适配iOS 15,通过以下方式实现图片多选:
func chooseImage() { var configuration = PHPickerConfiguration() configuration.selectionLimit = 0 // 配置为有序选择 configuration.selection = .ordered configuration.filter = .images let picker = PHPickerViewController(configuration: configuration) picker.delegate = self present(picker, animated: true) }
但发现按0.png、1.png、2.png、3.png、4.png的顺序选择图片时,PHPickerViewControllerDelegate中返回的结果顺序随机(例如3.png、2.png、4.png、0.png、1.png)。以下是我们的代理实现代码,无论是否使用DispatchQueue,结果顺序均随机:
class NewNoteViewController: UIViewController { static let theDispatchQueue = DispatchQueue( label: "com.xxx.yyy.theDispatchQueue", qos: .userInitiated, target: nil ) } extension NewNoteViewController: PHPickerViewControllerDelegate { func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true) guard !results.isEmpty else { return } print(">>>>> start the for loop") for result in results { result.itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.image.identifier) { [weak self] (url, error) in NewNoteViewController.theDispatchQueue.sync { self?.process(url) } } } } private func process(_ url: URL?) { precondition(!Thread.isMainThread) guard let url = url else { return } print(">>>>> url \(url)") ... } }
请问出现这种随机顺序的原因是什么?
原因分析
results数组本身的顺序完全符合你选择图片的顺序,问题根源在于loadFileRepresentation(forTypeIdentifier:completionHandler:)方法。它是异步执行的文件加载方法,每个PHPickerResult对应的图片加载耗时受图片大小、存储位置(比如是否为iCloud云端图片、本地缓存状态)等因素影响,不同结果的加载完成时间不一致,导致回调触发的顺序是随机的。- 你使用的
theDispatchQueue.sync仅能保证process方法在同一个串行队列中执行,避免多线程冲突,但无法改变回调本身被触发的先后顺序。比如选择顺序中的第一张图片加载耗时较长,而后面的图片加载更快,那么后面图片的回调会先被触发,先进入串行队列执行process,最终打印出来的URL顺序就会和选择顺序不符。
内容的提问来源于stack exchange,提问作者Cheok Yan Cheng
相关产品推荐
相关产品推荐

