如何用UISaveVideoAtPathToSavedPhotosAlbum实现从URL保存视频到相册的简易Swift代码
如何用UISaveVideoAtPathToSavedPhotosAlbum实现从URL保存视频到相册的简易Swift代码
我完全懂你想要简洁代码的心情!你之前写的图片保存逻辑非常清晰,视频保存其实也可以沿用类似的思路,而且真的不用写一大堆@objc代码~
极简版代码(无回调,和存图片逻辑一致)
这个版本和你存图片的代码几乎一模一样,完全不用额外的@objc代码,直接就能跑:
func saveVideo() { // 替换成你的视频URL guard let videoURL = URL(string: "https://v16m-default.akamaized.net/fe144652a33b4df42aad6ac47ede1534/67277349/video/tos/useast2a/tos-useast2a-ve-0068c003/00a9393b3a6246b99081a11348575483/?a=0&bti=OUBzOTg7QGo6OjZAL3AjLTAzYCMxNDNg&ch=0&cr=0&dr=0&er=0&lr=all&net=0&cd=0%7C0%7C0%7C0&cv=1&br=5010&bt=2505&cs=0&ds=6&ft=XE5bCqT0m7jPD12iKoYJ3wU2Y3yKMeF~O5&mime_type=video_mp4&qs=0&rc=ZGRoOzloZzw0PGU3NDY1aUBpanlrNHN0OHdndjMzNTczM0BhLy1hXzIxXy0xLS1iMi0xYSMzL3NnNDI0NC9fLS0uMTZzcw%3D%3D&vvpl=1&l=202411030657353C428D976FE213CC387E&btag=e00088000") else { return } DispatchQueue.global().async { // 异步下载视频数据 guard let videoData = try? Data(contentsOf: videoURL) else { print("视频下载失败") return } // 创建临时文件路径,用于存放下载的视频 let tempDirectory = NSTemporaryDirectory() let tempFilePath = tempDirectory + "temp_video.mp4" let tempFileURL = URL(fileURLWithPath: tempFilePath) do { // 把视频数据写入临时文件 try videoData.write(to: tempFileURL) DispatchQueue.main.async { // 调用系统方法保存视频到相册,target和selector传nil就不用写@objc回调 UISaveVideoAtPathToSavedPhotosAlbum(tempFilePath, nil, nil, nil) // 可选:保存完成后删除临时文件,释放空间 try? FileManager.default.removeItem(at: tempFileURL) } } catch { print("临时文件写入失败:\(error.localizedDescription)") } } }
带保存结果回调的版本
要是你想在保存完成后给用户提示(比如成功弹框、失败报错),只需要加一个超简单的@objc回调方法就行,完全算不上“ tons of code”:
第一步:添加回调方法
在你的ViewController里添加这个方法:
@objc private func videoSaveCompleted(_ success: Bool, error: Error?, contextInfo: UnsafeMutableRawPointer?) { DispatchQueue.main.async { if success { print("视频已成功保存到相册!") // 这里可以加UIAlertController提示用户 } else { print("保存失败:\(error?.localizedDescription ?? "未知错误")") } } }
第二步:修改保存代码
把之前的保存行替换成:
UISaveVideoAtPathToSavedPhotosAlbum(tempFilePath, self, #selector(videoSaveCompleted(_:error:contextInfo:)), nil)
大视频优化版本
上面的Data(contentsOf:)适合小视频,要是保存长视频,建议用URLSession流式下载,避免内存暴涨,代码同样简洁:
func saveLargeVideo() { guard let videoURL = URL(string: "你的视频URL") else { return } // 用URLSession异步下载视频到临时文件 let downloadTask = URLSession.shared.downloadTask(with: videoURL) { tempURL, _, error in guard let tempURL = tempURL, error == nil else { print("下载失败:\(error?.localizedDescription ?? "未知错误")") return } // 把系统生成的临时文件移到我们自己的路径(系统临时文件会被自动删除) let destDir = NSTemporaryDirectory() let uniqueFileName = UUID().uuidString + ".mp4" let destURL = URL(fileURLWithPath: destDir).appendingPathComponent(uniqueFileName) do { try FileManager.default.moveItem(at: tempURL, to: destURL) DispatchQueue.main.async { // 调用保存方法,这里用带回调的版本 UISaveVideoAtPathToSavedPhotosAlbum(destURL.path, self, #selector(videoSaveCompleted(_:error:contextInfo:)), nil) // 保存后删除临时文件 try? FileManager.default.removeItem(at: destURL) } } catch { print("文件移动失败:\(error.localizedDescription)") } } downloadTask.resume() }
重要提醒
你已经添加了Privacy - Photo Library Additions Usage Description到Info.plist里,这一步非常关键,否则会出现权限问题或者崩溃哦~
这样就搞定啦,和你存图片的体验一样简单,希望能帮到你 😊
备注:内容来源于stack exchange,提问作者Антон Разгуляев




