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

iOS开发如何将应用内视频保存到用户照片库?现有报错代码如何优化?

iOS 视频保存到相册的问题修复与最优实现

现有代码的核心问题

  • API过时错误:UTTypeCopyPreferredTagWithClass是iOS 15之前的旧API,在引入UniformTypeIdentifiers框架后已经被废弃,替换为Swift原生的UTType属性调用,所以会提示不在作用域内。
  • 逻辑错误:你调用了图片写入的方法PHAssetChangeRequest.creationRequestForAssetFromImage,就算修复了编译错误也无法写入视频到相册。
  • 错误处理缺失:代码中多处使用try?忽略抛出的错误,出现异常时无法定位问题。
  • 权限逻辑缺失:未判断相册写入权限,系统会直接拦截写入操作。

优化后的正确实现方案

请先在项目的Info.plist中添加NSPhotoLibraryAddUsageDescription权限声明,填写用户允许相册写入的提示文案,否则写入操作会直接被系统拦截。

完整实现代码:

import UniformTypeIdentifiers
import Photos

func saveVideoToAlbum(videoData: Data, videoUTI: UTType) throws {
    // 1. 生成临时文件路径
    guard let fileExtension = videoUTI.preferredFilenameExtension else {
        throw NSError(domain: "VideoSaveError", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效的视频格式"])
    }
    let fileName = "\(ProcessInfo.processInfo.globallyUniqueString).\(fileExtension)"
    let tempURL = FileManager.default.temporaryDirectory.appendingPathComponent(fileName)
    
    // 2. 写入视频数据到临时路径
    try videoData.write(to: tempURL, options: .atomic)
    
    // 3. 请求相册写入权限(iOS14+支持仅添加权限,用户体验更好)
    PHPhotoLibrary.requestAuthorization(for: .addOnly) { status in
        guard status == .authorized else {
            // 可自行补充权限拒绝的提示逻辑
            try? FileManager.default.removeItem(at: tempURL)
            return
        }
        
        // 4. 写入视频到相册
        PHPhotoLibrary.shared().performChanges {
            // 调用视频专属写入接口
            PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: tempURL)
        } completionHandler: { success, error in
            // 写入完成后删除临时文件释放空间
            try? FileManager.default.removeItem(at: tempURL)
            if let error = error {
                // 可自行补充写入失败的提示逻辑
                print("视频保存失败:\(error.localizedDescription)")
            } else if success {
                // 可自行补充保存成功的回调逻辑
            }
        }
    }
}

调用示例:
如果你的视频是MP4格式,直接传入对应UTI即可:

do {
    try saveVideoToAlbum(videoData: 你的视频Data变量, videoUTI: .mpeg4Movie)
} catch {
    print("预处理失败:\(error.localizedDescription)")
}

轻量可选方案

如果不需要自定义写入逻辑,只需要快速保存已经存在本地的视频文件,可以使用更简洁的系统兼容方法:

// 传入视频本地路径即可,兼容iOS 3.0+
UISaveVideoAtPathToSavedPhotosAlbum(videoPath, self, #selector(videoSaveCompleted(_:didFinishSavingWithError:contextInfo:)), nil)

// 保存结果回调方法
@objc func videoSaveCompleted(_ path: String, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
    if let error = error {
        print("保存失败:\(error.localizedDescription)")
    } else {
        print("保存成功")
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 13:00:01