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

Swift应用内拍照保存后,检索Asset时缺失GPS信息问题

解决UIImagePickerController拍照后保存照片丢失GPS信息的问题

这个问题我之前踩过坑!核心原因是**UIImage对象本身不包含照片的元数据(比如GPS、拍摄参数这些)**,你直接用UIImageWriteToSavedPhotosAlbum保存的只是纯像素数据,原始照片的GPS等元信息被丢掉了。下面是具体的解决思路和代码:

问题根源

当你用UIImagePickerController拍照时,原始照片的完整元数据(包括GPS)其实存在info字典的UIImagePickerControllerMediaMetadata键里,但UIImagePickerControllerOriginalImage对应的UIImage是剥离了元数据的纯图像。你之前的代码只拿到了图像,没把元数据一起存进去,所以相册里的Asset就没有GPS信息了。

解决方案:保留元数据并通过PHPhotoLibrary保存

我们需要用PHPhotoLibrary来保存带有元数据的图片(替代UIImageWriteToSavedPhotosAlbum),同时要把原始的GPS元数据附加到压缩后的图片上。

步骤1:修改图片选择完成的回调逻辑

@objc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    picker.dismiss(animated: true, completion: nil)
    photoChanged = true
    
    // 1. 取出原始图片和完整元数据
    guard let originalImage = info[.originalImage] as? UIImage,
          let originalMetadata = info[.mediaMetadata] as? [String: Any] else {
        return
    }
    
    // 2. 压缩图片(你的原有逻辑)
    guard let compressedImage = originalImage.resizeWithWidth(width: 450) else {
        return
    }
    
    // 3. 提取并保留GPS元数据(防止压缩过程丢失)
    var finalMetadata = originalMetadata
    if let gpsData = originalMetadata[kCGImagePropertyGPSDictionary as String] {
        finalMetadata[kCGImagePropertyGPSDictionary as String] = gpsData
    }
    
    // 4. 调用自定义方法保存带元数据的图片
    saveImageWithMetadataToAlbum(image: compressedImage, metadata: finalMetadata)
}

步骤2:实现带元数据的保存方法

private func saveImageWithMetadataToAlbum(image: UIImage, metadata: [String: Any]) {
    // 先请求照片库写入权限
    PHPhotoLibrary.requestAuthorization { status in
        guard status == .authorized else {
            print("需要授予照片库写入权限才能保存图片")
            return
        }
        
        DispatchQueue.main.async {
            PHPhotoLibrary.shared().performChanges({
                // 创建图片保存请求
                let creationRequest = PHAssetCreationRequest.forAsset()
                // 传入压缩后的图片数据
                guard let imageData = image.jpegData(compressionQuality: 0.8) else { return }
                creationRequest.addResource(with: .photo, data: imageData, options: nil)
                
                // 附加GPS元数据(两种方式选其一)
                // 方式1:直接设置位置(从元数据解析)
                if let gpsDict = metadata[kCGImagePropertyGPSDictionary as String] as? [String: Any],
                   let location = CLLocation(gpsDictionary: gpsDict) {
                    creationRequest.location = location
                }
                // 方式2:直接传入完整元数据(保留更多拍摄信息)
                // creationRequest.metadata = metadata
                
            }) { success, error in
                if success {
                    print("图片保存成功,GPS信息已保留")
                } else {
                    print("保存失败:\(error?.localizedDescription ?? "未知错误")")
                }
            }
        }
    }
}

额外注意事项

  • 权限配置:在Info.plist里添加NSPhotoLibraryAddUsageDescription(iOS 11+)或NSPhotoLibraryUsageDescription(iOS 10及以下)的描述文本,否则权限请求会被拒绝。
  • 压缩方法的影响:如果你的resizeWithWidth方法是基于UIImage处理的,生成的新图片本身还是没有元数据的,所以必须手动把原始GPS元数据附加到保存请求中。
  • 扩展功能:如果需要保留更多元数据(比如拍摄时间、相机型号),直接使用creationRequest.metadata = metadata即可,无需单独提取GPS。

这样保存后的相册Asset就会包含原始拍摄的GPS信息啦!

内容的提问来源于stack exchange,提问作者samuscarella

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:38:52