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

为自定义相机拍摄的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 23:25:32