iOS中使用PHPicker导入AVIF图片时获取原始数据为空的问题
问题
使用PHPicker实现用户导入照片功能,但UIImage不支持AVIF格式图片,因此希望获取AVIF图片的原始数据。当前代码选择AVIF图片时,itemProvider可通过kUTTypeImage类型标识符加载并获取本地路径,但使用Data(contentsOf:)读取原始数据时得到空数据,改用NSData(contentsOf:)结果仍为空。
当前代码如下:
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true) for image in results { loadImagePickerResult(image: image) } } func loadImagePickerResult(image: PHPickerResult) { if image.itemProvider.canLoadObject(ofClass: UIImage.self) { image.itemProvider.loadObject(ofClass: UIImage.self) { [weak self] newImage, error in guard let self = self else { return } if let _ = error { } else if let needAddImage = newImage as? UIImage { let imageItem = ContentImageItem() imageItem.image = needAddImage self.viewModel.selectedImageList.append(imageItem) DispatchQueue.main.async { self.scrollImageView.reloadData() self.checkConfirmState() } } } } else if image.itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) { image.itemProvider.loadItem(forTypeIdentifier: kUTTypeImage as String, options: nil) { [weak self] item, error in guard let self = self else { return } guard let url = item as? URL else { return } var imageData: Data? do { imageData = try Data(contentsOf: url, options: [.mappedIfSafe, .alwaysMapped]) } catch { } guard let selectedImageData = imageData else { return } /// selectedImageData is empty data } } else { } }
解决方法
问题根源
PHPicker返回的URL是系统沙盒内的临时文件URL,直接用Data(contentsOf:)读取会存在权限限制或临时文件未正确映射的问题,导致读取到空数据。正确的做法是利用NSItemProvider的loadDataRepresentation(forTypeIdentifier:completionHandler:)方法直接获取文件的原始数据,而非先拿URL再读取。
修改后的代码
替换原代码中else if image.itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String)块的内容:
else if image.itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) { image.itemProvider.loadDataRepresentation(forTypeIdentifier: kUTTypeImage as String) { [weak self] data, error in guard let self = self else { return } guard let selectedImageData = data, error == nil else { // 这里添加错误处理逻辑,比如提示用户导入失败 return } // 处理AVIF原始数据,示例:假设ContentImageItem支持存储原始数据 let imageItem = ContentImageItem() imageItem.imageData = selectedImageData self.viewModel.selectedImageList.append(imageItem) DispatchQueue.main.async { self.scrollImageView.reloadData() self.checkConfirmState() } } }
额外说明
- 如果需要针对AVIF格式单独处理,可先判断类型标识符是否为
kUTTypeAVIF(需导入MobileCoreServices框架),再调用loadDataRepresentation,逻辑更精准。 - 不要忽略错误处理,回调中需处理用户取消授权、文件损坏等异常情况。
内容的提问来源于stack exchange,提问作者zZz
相关产品推荐
相关产品推荐

