为自定义相机拍摄的UIImage添加GPS数据失败,求排查
问题分析与解决
你的代码核心问题出在最后把带GPS元数据的Data转成UIImage这一步——UIImage对象本身并不存储EXIF、GPS这类图片元数据,它只包含像素和基础显示信息。所以当你把mutableData转成UIImage后,之前添加的GPS元数据会直接丢失,后续保存这个UIImage到相册自然没有位置信息。
修正方案
直接使用包含GPS元数据的Data来保存到相册,不要经过UIImage中转。调整代码逻辑如下:
1. 修改函数返回带元数据的Data
把原函数的返回类型从UIImage改成Data,直接返回包含GPS信息的图片数据:
func addLocationToImageData(image: UIImage, location: CLLocation) throws -> Data { guard let data = image.jpegData(compressionQuality: 1.0) else { throw NSError(domain: "error", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to get JPEG data from image."]) } let metadata = NSMutableDictionary() let gpsDict = NSMutableDictionary() let latitude = location.coordinate.latitude let longitude = location.coordinate.longitude // 写入GPS核心坐标信息 gpsDict[(kCGImagePropertyGPSLatitude as String)] = abs(latitude) gpsDict[(kCGImagePropertyGPSLatitudeRef as String)] = latitude < 0.0 ? "S" : "N" gpsDict[(kCGImagePropertyGPSLongitude as String)] = abs(longitude) gpsDict[(kCGImagePropertyGPSLongitudeRef as String)] = longitude < 0.0 ? "W" : "E" // 可选:补充拍摄时间戳,让元数据更完整 gpsDict[(kCGImagePropertyGPSTimeStamp as String)] = location.timestamp gpsDict[(kCGImagePropertyGPSDateStamp as String)] = ISO8601DateFormatter().string(from: location.timestamp) metadata[(kCGImagePropertyGPSDictionary as String)] = gpsDict guard let source = CGImageSourceCreateWithData(data as CFData, nil) else { throw NSError(domain: "error", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to create image source from data."]) } let uti = CGImageSourceGetType(source)! let mutableData = NSMutableData(data: data) guard let destination = CGImageDestinationCreateWithData(mutableData, uti, 1, nil) else { throw NSError(domain: "error", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to create image destination."]) } CGImageDestinationAddImageFromSource(destination, source, 0, metadata) guard CGImageDestinationFinalize(destination) else { throw NSError(domain: "error", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to write image with metadata to data."]) } return mutableData as Data }
2. 直接保存Data到相册
调用上述函数得到带元数据的Data后,用PHAssetCreationRequest保存,确保元数据被完整保留:
import Photos // 假设你已经获取到拍摄的image和当前location do { let imageDataWithGPS = try addLocationToImageData(image: capturedImage, location: currentLocation) PHPhotoLibrary.requestAuthorization { status in guard status == .authorized else { return } PHPhotoLibrary.shared().performChanges({ let creationRequest = PHAssetCreationRequest.forAsset() creationRequest.addResource(with: .photo, data: imageDataWithGPS, options: nil) }) { success, error in if let error = error { print("保存失败:\(error.localizedDescription)") } else { print("图片带位置信息保存成功") } } } } catch { print("添加位置信息失败:\(error.localizedDescription)") }
额外排查点
- 确认App已获取精确位置权限,Info.plist中需配置
NSLocationWhenInUseUsageDescription或NSLocationAlwaysAndWhenInUseUsageDescription - 如果原图片是PNG格式,可将
jpegData替换为pngData(),但同样要通过Data保存,不能转成UIImage后再存储 - 保存后可通过Mac预览的「显示检查器」查看图片元数据,确认GPS信息是否存在
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

