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
相关产品推荐
相关产品推荐

