iOS 17中PHPickerResult.itemProvider.canLoadObject返回false的问题咨询
PHPickerViewController在iOS 17中itemProvider.canLoadObject(UIImage.self)偶发返回false的问题
问题详情
我使用PHPickerViewController选图时,在代理方法里通过以下代码加载图片:
results.forEach { if $0.itemProvider.canLoadObject(ofClass: UIImage.self) { $0.itemProvider.loadObject(ofClass: UIImage.self) { [weak self] image, error in guard let image = image as? UIImage else { return } } } }
这段代码在iOS 12~16系统中运行正常,但到了iOS 17,itemProvider.canLoadObject(ofClass: UIImage.self)会时不时直接返回false,导致图片加载失败。
问题最初出现在iOS 17.0.3,升级到iOS 17.1时曾短暂消失,但iOS 17.1.1版本又复现了该bug。
现有临时方案的弊端
我了解到有讨论提到用PHAsset.fetchAssets作为临时解决方案,但这个方法会破坏用户体验:
- PHPickerViewController本身无需相册权限就能弹出并展示所有照片,但使用PHAsset会在用户完成选择时触发权限请求;
- 如果应用仅拥有相册有限访问权限,可能无法加载用户选中但被限制的照片。
无需权限的替代解决方案
方案1:跳过canLoadObject判断,直接尝试加载
既然canLoadObject在iOS 17存在偶发误判,可直接调用loadObject,在回调中处理失败情况:
results.forEach { $0.itemProvider.loadObject(ofClass: UIImage.self) { [weak self] image, error in guard let image = image as? UIImage else { // 加载失败时的处理逻辑,比如打印错误或提示用户 if let error = error { print("图片加载失败:\(error.localizedDescription)") } return } // 处理成功加载的图片 } }
方案2:通过UTType加载数据再转成UIImage
如果直接加载UIImage失败,可借助UniformTypeIdentifiers框架(iOS 14+支持),先加载图片数据再转成UIImage,该方法无需相册权限:
import UniformTypeIdentifiers results.forEach { result in let imageUTType = UTType.image if result.itemProvider.hasItemConformingToTypeIdentifier(imageUTType.identifier) { result.itemProvider.loadDataRepresentation(forTypeIdentifier: imageUTType.identifier) { data, error in guard let data = data, let image = UIImage(data: data) else { if let error = error { print("图片数据加载失败:\(error.localizedDescription)") } return } // 处理转换后的图片 } } }
总结
iOS 17的itemProvider.canLoadObject(UIImage.self)存在偶发返回false的bug,建议直接跳过该判断尝试加载,或者使用基于UTType的方式加载图片数据,既能避开bug,又不会因请求相册权限影响用户体验。
内容的提问来源于stack exchange,提问作者iMoeNya
相关产品推荐
相关产品推荐

