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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 04:28:14