iOS写入图像EXIF元数据时部分参数错误或不显示如何修复
EXIF写入异常修复方案
问题原因与对应修复方法
- DateTimeOriginal参数丢失:EXIF标准强制要求该字段格式为
YYYY:MM:DD HH:MM:SS的字符串,你当前传入的毫秒时间戳不符合格式规范,系统写入时会直接丢弃非法字段,需要先将时间转换为符合要求的格式。 - FileSource参数值错误:
kCGImagePropertyExifFileSource对应EXIF标准中的枚举类型字段,仅支持传入1/2/3三个数字值(分别对应胶片扫描、反光扫描、数码相机场景),不支持字符串类型的路径值。如果你需要存储文件路径信息,建议改用kCGImagePropertyExifUserComment等支持字符串类型的EXIF字段。 - 优化建议:写入时优先保留原图片的元数据,仅新增/修改目标字段,避免覆盖其他默认EXIF信息。
修复后完整代码
// 提前定义EXIF专用日期格式化器,避免重复创建损耗性能 private static let exifDateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateFormat = "yyyy:MM:dd HH:mm:ss" formatter.timeZone = TimeZone(secondsFromGMT: 0) // 按需调整为时区,默认使用UTC时间 formatter.locale = Locale(identifier: "en_US_POSIX") // 避免系统语言影响格式输出 return formatter }() static func encodeImage(at url: URL, file: File, completionHandler: ((URL?) -> Void)?) { let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as URL let filePath = documentsDirectory.appendingPathComponent("\(UUID().uuidString)\(file.fileExtension ?? ".jpg")") guard let data = NSData(contentsOf: url), let src = CGImageSourceCreateWithData(data, nil), let uti = CGImageSourceGetType(src), let cfPath = CFURLCreateWithFileSystemPath(nil, filePath.path as CFString, CFURLPathStyle.cfurlposixPathStyle, false), let dest = CGImageDestinationCreateWithURL(cfPath, uti, 1, nil), // 读取原图片的元数据 let originalProperties = CGImageSourceCopyPropertiesAtIndex(src, 0, nil) as? [String: Any] else { completionHandler?(nil) return } // 合并新的EXIF参数到原有元数据中 var mutableProperties = originalProperties var exifDict = mutableProperties[kCGImagePropertyExifDictionary as String] as? [String: Any] ?? [:] // 写入机身序列号 exifDict[kCGImagePropertyExifBodySerialNumber as String] = file.device ?? "0" // 写入文件路径到UserComment字段,替换原来错误的FileSource exifDict[kCGImagePropertyExifUserComment as String] = file.deviceUrl ?? file.path // 写入符合格式要求的拍摄时间 exifDict[kCGImagePropertyExifDateTimeOriginal as String] = exifDateFormatter.string(from: file.createdAt) mutableProperties[kCGImagePropertyExifDictionary as String] = exifDict CGImageDestinationAddImageFromSource(dest, src, .zero, mutableProperties as CFDictionary) if CGImageDestinationFinalize(dest) { completionHandler?(filePath) } else { completionHandler?(nil) } }
内容的提问来源于stack exchange,提问作者DevSemenuk
相关产品推荐
相关产品推荐

