Swift / SwiftUI -在设备锁定/被置于后台之前执行函数?



我正在开发一个记录视频片段的应用程序(参考Instagram的卷轴),我目前正在处理应用程序移动到背景/屏幕被锁定时的状态。

目前的问题是,如果我将应用程序移动到后台/锁定屏幕在正在进行的视频录制AVCaptureFileOutputRecordingDelegate的fileOutput方法无法保存视频。我曾尝试在。plist中添加"所需的背景模式",我也偶然发现了以下线索,现在我不确定是否有可能在应用程序移动到背景时实际保存正在进行的视频录制,以及如果这样做是一个好主意,如果你想遵守隐私准则。

我想知道是否有一种方法可以延迟应用程序被移动到后台,这样我就可以执行我通常用来在设备结束在后台之前停止和保存视频记录的方法(最终无法为我保存视频的过程)。

注意:把我的方法保存/停止正在进行的视频录制在以下观察不起作用,它会失败,如上所述:

.onReceive(NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)) { _ in
print("Moving to the background!")
toggleRecording() <--- this normally stops and saves the recording but it fails here.
}

感谢您提供的任何输入!

研究场景协议

我报价…

场景协议提供场景修改器,定义为协议具有默认实现的方法,您可以使用它来配置现场。例如,您可以使用onChange(of:perform:)修饰符来当值更改时触发操作。下面的代码清空a当窗口组中的所有场景都移动到背景:

需要说明的是,这是苹果公司提供的例子…

struct MyScene: Scene {
@Environment(.scenePhase) private var scenePhase
@StateObject private var cache = DataCache()
var body: some Scene {
WindowGroup {
MyRootView()
}
.onChange(of: scenePhase) { newScenePhase in
if newScenePhase == .background {
cache.empty()
}
}
}
}

并且根据您的情况,您可以将cache.empty命令替换为toggleRecording()

下面的代码解决了我的特殊情况:

当app放到后台调用AVCaptureFileOutputRecordingDelegate时,不可避免地会出现错误。如果发生这种情况,我告诉应用程序寻找任何记录的数据从url (var activeRecordingUrl: URL?),我在开始记录时生成/更新。如果找到了数据(对我来说似乎总是这样),我就会像"手动"录制一样存储它。


extension CameraViewController: AVCaptureFileOutputRecordingDelegate {
func fileOutput(
_ output: AVCaptureFileOutput,
didFinishRecordingTo outputFileURL: URL,
from connections: [AVCaptureConnection],
error: Error?
) {
guard error == nil else {
// --------- Start of fix ---------
NSLog("> ERROR: Recording was interrupted: (String(describing: error?.localizedDescription)), attempting to salvage record data from activeRecordingUrl.")

guard let outputUrl = activeRecordingUrl else {
NSLog("> ERROR: found nil when unwrapping activeRecordingUrl.")
onRecordingFinished(false)
return
}

recordings.append(VideoSegment(avAssetUrl: outputUrl, cameraPosition: sessionInput.device.position, avAsset: AVAsset(url: outputUrl)))
NSLog("Found record data from the session that was interrupted.")

onRecordingFinished(true)
// --------- End of fix ---------
return
}
recordings.append(VideoSegment(
avAssetUrl: outputFileURL,
cameraPosition: sessionInput.device.position,
avAsset: AVAsset(url: outputFileURL
)))
onRecordingFinished(true)
}
}

最新更新