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

如何保存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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:55:52