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

iOS中UIImage调用jpegData转Data报HEIC格式不支持错误

问题说明

使用UIImagePickerController实现系统相册选图、相机拍摄功能时,在imagePickerController代理回调方法中获取到UIImage实例后,尝试通过如下代码转换为图片Data:

let uiImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
let imageData = uiImage.jpegData(compressionQuality: 1)! // 该行执行抛出错误

执行第二行转换代码时持续抛出如下错误:

findWriterForTypeAndAlternateType:119: unsupported file format 'public.heic'

异常现象:直接通过Image(uiImage)方式更新图片视图时,视图可以正常加载显示对应图片,无法定位错误触发原因。

问题根因
  • 报错核心触发逻辑:苹果从iOS 11开始默认使用HEIC/HEIF作为系统图片的高效存储格式,当你从相册/相机拿到的UIImage关联的底层资源是HEIC格式,且存在iCloud资源未完全下载、原始HEIC元数据缺失的情况时,直接调用jpegData(compressionQuality:)方法,系统底层编码组件无法自动完成HEIC到JPEG的转码流程,就会抛出HEIC格式不支持的错误。
  • Image(uiImage)可以正常显示的原因:SwiftUI的Image组件渲染时仅使用UIKit层已经解码完成的位图像素数据,不需要校验原始图片的完整格式元数据,也不需要对原始资源做二次编码,因此不会触发该报错。
  • 代码里的强制解包!会在转码失败时直接触发应用崩溃,属于高风险写法。
可行解决方案

方案1:重绘图片后转码(兼容性最高,推荐优先使用)

拿到原始UIImage后先重新绘制生成新的位图实例,抹除原始HEIC格式的元数据关联,再执行JPEG转码,可覆盖所有选图、拍照场景:

// 基于原始UIImage尺寸创建渲染器
let renderer = UIGraphicsImageRenderer(size: uiImage.size)
// 重绘生成不带原始元数据的新UIImage实例
let redrawnImage = renderer.image { _ in
    uiImage.draw(in: CGRect(origin: .zero, size: uiImage.size))
}
// 转JPEG数据,避免强制解包,做好失败兜底
guard let imageData = redrawnImage.jpegData(compressionQuality: 0.8) else {
    // 转码失败时的业务兜底逻辑,比如提示用户图片处理失败
    return
}

方案2:配置图片选择器从源头输出JPEG格式资源

初始化UIImagePickerController时,直接指定导出的媒体类型为JPEG,避免拿到HEIC格式资源:

import UniformTypeIdentifiers

let picker = UIImagePickerController()
// 配置选择器仅返回JPEG格式媒体
picker.mediaTypes = [UTType.jpeg.identifier]
// 相机拍摄场景额外配置,强制拍摄输出JPEG
if picker.sourceType == .camera {
    picker.cameraCaptureMode = .photo
    if #available(iOS 11.0, *) {
        picker.videoExportPreset = AVAssetExportPresetPassthrough
    }
}

注意:该方案需要引入UniformTypeIdentifiers、AVFoundation框架,低于iOS 14的版本需要做UTType的适配判断。

方案3:直接读取原始资源Data做处理

跳过originalImage转UIImage再转Data的流程,直接从代理回调的info字典中读取原始图片URL,加载原始Data后自行处理格式:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    picker.dismiss(animated: true)
    // 优先读取相册资源的原始URL
    if let imageURL = info[.imageURL] as? URL,
       let originalData = try? Data(contentsOf: imageURL) {
        // 此处拿到原始图片Data,可自行判断格式后按需转码
        // 若需要转JPEG,可结合方案1的重绘逻辑处理
        return
    }
    // 相机拍摄无本地URL的场景,再走originalImage重绘转码逻辑
}

内容的提问来源于stack exchange,提问作者KANAYO AUGUSTIN UG

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 17:48:14