Swift/SwiftUI 如何在设备锁屏或应用进后台前执行视频保存操作
问题根因
你遇到的保存失败本质是:UIApplication.willResignActiveNotification 触发时,系统已经开始回收音视频采集相关的前台权限,停止录制的异步操作还没完成写入流程,应用就被系统挂起,导致写入中断、代理回调无法正常触发。
普通状态下应用进入后台后会被立刻冻结,未完成的IO操作都会被暂停,自然无法正常保存视频。
可行解决方案
苹果官方提供了后台任务申请接口用于处理这类退后台前需要收尾的短耗时操作,完全符合隐私规范,不需要配置特殊的后台模式,也不会被审核驳回:
你只需要在收到退后台通知时,先向系统申请最长30秒的额外后台执行时间,等视频保存完成后再主动结束后台任务即可。
合规说明:该方案仅用于收尾当前正在进行的用户主动发起的录制操作,不会在后台持续采集音视频,完全符合苹果隐私要求。如果你没有后台持续采集的需求,不需要在plist中添加
required background modes配置,避免审核时产生不必要的疑问。
代码实现示例
首先在视图中声明后台任务标识变量:
@State private var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
然后修改通知监听逻辑:
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)) { _ in guard isRecording else { return } // 没有正在录制的任务直接跳过 // 申请后台执行时间 backgroundTaskID = UIApplication.shared.beginBackgroundTask { [weak self] in // 后台时间到期回调:如果还没保存完也要强制结束任务,避免系统杀进程 guard let self = self else { return } if self.backgroundTaskID != .invalid { UIApplication.shared.endBackgroundTask(self.backgroundTaskID) self.backgroundTaskID = .invalid } } // 执行停止录制逻辑 toggleRecording() }
最后在录制保存完成的代理回调中,主动结束后台任务:
func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) { // 原有保存逻辑处理... // 保存完成后结束后台任务 if backgroundTaskID != .invalid { UIApplication.shared.endBackgroundTask(backgroundTaskID) backgroundTaskID = .invalid } }
额外注意事项
- 不要依赖
UIApplication.willResignActiveNotification的同步执行结果,停止录制、写入文件都是异步操作,必须等代理回调触发才算保存完成 - 该方案默认能拿到最多30秒的后台执行时间,足够处理常规短视频的保存操作,如果是超过10分钟的长视频,建议加个分片写入逻辑,避免单文件写入耗时太长超过后台时间限制
- 如果你的应用本身有后台持续采集的需求(比如直播类应用),再考虑添加后台音视频采集的权限配置,普通短视频录制场景不需要该配置
内容的提问来源于stack exchange,提问作者justaplaceholdername
相关产品推荐
相关产品推荐

