diff --git a/BetterCapture/Service/CameraSession.swift b/BetterCapture/Service/CameraSession.swift index c64372c..00ae584 100644 --- a/BetterCapture/Service/CameraSession.swift +++ b/BetterCapture/Service/CameraSession.swift @@ -75,10 +75,13 @@ final class CameraSession { session = newSession // Wait for the session to actually be running before returning. + // AVCaptureSession is not Sendable, but we fully configure it on + // the main actor above and then only touch it on `queue` below. + nonisolated(unsafe) let runnable = newSession let isRunning = await withCheckedContinuation { continuation in queue.async { - newSession.startRunning() - continuation.resume(returning: newSession.isRunning) + runnable.startRunning() + continuation.resume(returning: runnable.isRunning) } } @@ -93,8 +96,10 @@ final class CameraSession { guard let current = session else { return } session = nil + // See comment in start(deviceID:) for why nonisolated(unsafe) is appropriate. + nonisolated(unsafe) let stoppable = current queue.async { - current.stopRunning() + stoppable.stopRunning() } logger.info("Camera session stopped") diff --git a/BetterCapture/ViewModel/RecorderViewModel.swift b/BetterCapture/ViewModel/RecorderViewModel.swift index 22dc88b..6be6fb7 100644 --- a/BetterCapture/ViewModel/RecorderViewModel.swift +++ b/BetterCapture/ViewModel/RecorderViewModel.swift @@ -223,7 +223,7 @@ final class RecorderViewModel { logger.info("Video size: \(self.videoSize.width)x\(self.videoSize.height)") // Access security-scoped output directory before writing - settings.startAccessingOutputDirectory() + _ = settings.startAccessingOutputDirectory() // Setup asset writer let outputURL = settings.generateOutputURL()