如何保存Live Photo?使用PHPhotoLibrary时遇NSCocoaErrorDomain Code=-1错误
解决Live Photo保存失败问题(NSCocoaErrorDomain Code=-1)
嘿,我看到你用PHAssetCreationRequest保存Live Photo时碰到了这个模糊的Code=-1错误,这类错误大多和资源配置、文件有效性或者权限有关,咱们一步步来排查修复:
1. 先确认文件本身没问题
首先得保证videoURL和imageURL指向的文件真的存在,而且你的App能访问它们:
- 如果是沙盒里的临时文件,检查路径拼写是否正确;
- 如果是从系统相册/文件App获取的URL,要确保你保留了安全书签(避免权限失效)。
可以在保存代码前加个简单的校验:
guard FileManager.default.fileExists(atPath: videoURL.path), FileManager.default.fileExists(atPath: imageURL.path) else { print("视频或照片文件不存在,请检查路径") return }
2. 给资源添加正确的配置选项
你现在用options: nil添加资源,但Live Photo的配对视频和照片需要明确的选项配置,尤其是视频时长要和照片的捕获逻辑匹配:
// 照片资源配置(如果是临时文件,设置shouldMoveFile可以节省空间) let imageOptions = PHAssetResourceCreationOptions() imageOptions.shouldMoveFile = true // 视频资源配置:必须指定时长,这是Live Photo识别的关键 let videoOptions = PHAssetResourceCreationOptions() videoOptions.shouldMoveFile = true if let videoAsset = AVURLAsset(url: videoURL) { videoOptions.duration = videoAsset.duration }
3. 调整资源添加的顺序
有些版本的Photos框架对资源添加顺序敏感,建议先添加照片资源,再添加配对视频:
request.addResource(with: .photo, fileURL: imageURL, options: imageOptions) request.addResource(with: .pairedVideo, fileURL: videoURL, options: videoOptions)
4. 确认照片库写入权限
别漏掉最基础的权限检查!确保你的App已经获得了相册写入权限:
- 在
Info.plist中添加NSPhotoLibraryAddUsageDescription(仅需要添加权限时)或NSPhotoLibraryUsageDescription(需要读写权限时),描述清楚为什么需要访问相册; - 保存前先请求权限:
PHPhotoLibrary.requestAuthorization(for: .addOnly) { status in guard status == .authorized else { print("没有相册写入权限,无法保存Live Photo") return } // 在这里执行你的保存逻辑 }
完整修正后的代码示例
把上面的要点整合起来,完整代码如下:
PHPhotoLibrary.requestAuthorization(for: .addOnly) { status in guard status == .authorized else { print("需要相册写入权限才能保存Live Photo") return } guard FileManager.default.fileExists(atPath: videoURL.path), FileManager.default.fileExists(atPath: imageURL.path) else { print("视频或照片文件不存在") return } PHPhotoLibrary.shared().performChanges({ let request = PHAssetCreationRequest.forAsset() // 配置资源选项 let imageOptions = PHAssetResourceCreationOptions() imageOptions.shouldMoveFile = true let videoOptions = PHAssetResourceCreationOptions() videoOptions.shouldMoveFile = true if let videoAsset = AVURLAsset(url: videoURL) { videoOptions.duration = videoAsset.duration } // 按正确顺序添加资源 request.addResource(with: .photo, fileURL: imageURL, options: imageOptions) request.addResource(with: .pairedVideo, fileURL: videoURL, options: videoOptions) }, completionHandler: { success, error in // 回到主线程处理结果 DispatchQueue.main.async { if success { print("Live Photo成功保存到相册🎉") } else { // 打印更详细的错误信息,方便排查 print("保存失败: \(error?.localizedDescription ?? "未知错误")") print("错误详情: \(error?.userInfo ?? [:])") } } }) }
如果还是不行,建议打印error?.userInfo,里面会包含更具体的失败原因,比如文件格式不支持、资源不匹配等。
内容的提问来源于stack exchange,提问作者j.thome
相关产品推荐
相关产品推荐

