Swift 6下AVCaptureSession启动崩溃问题求助
Swift 6 下 AVCaptureSession 崩溃问题修复方案
核心问题分析
崩溃源于Swift 6严格并发模式下,AVCaptureSession相关操作的线程安全违规和Actor隔离冲突,具体体现在代理方法的线程切换错误、属性跨线程未同步访问、以及Sendable合规性缺失。
具体修复步骤
- 确保类遵循Sendable协议
Swift 6严格并发要求跨线程捕获的对象必须符合Sendable,给Camera类添加协议遵循:
class Camera: Sendable { private let sessionQueue = DispatchQueue(label: "CameraSessionQueue") private var captureSession = AVCaptureSession() private var deviceInput: AVCaptureDeviceInput? private var photoOutput: AVCapturePhotoOutput? private var videoOutput: AVCaptureVideoDataOutput? private var isCaptureSessionConfigured = false // 其他属性和方法... }
- 修正代理方法的线程逻辑
你给captureOutput标记了@MainActor,但AVCaptureVideoDataOutput的代理方法默认在你指定的VideoDataOutputQueue执行,强行切换主线程会导致AVCaptureConnection的修改不在sessionQueue上执行(违反AVCaptureSession线程安全规则)。拆分操作:
- 修改AVCaptureConnection的逻辑必须放到sessionQueue执行
- 更新预览UI的逻辑切换到主线程
extension Camera: @preconcurrency AVCaptureVideoDataOutputSampleBufferDelegate { func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { guard let pixelBuffer = sampleBuffer.imageBuffer else { return } // 处理连接旋转:必须在sessionQueue执行 sessionQueue.async { [weak self] in guard let self = self, let device = self.captureDevice else { return } let rotationCoordinator = AVCaptureDevice.RotationCoordinator( device: device, previewLayer: nil ) if connection.isVideoOrientationSupported { connection.videoRotationAngle = rotationCoordinator.videoRotationAngleForHorizonLevelCapture } } // 更新预览UI:切换到主线程 DispatchQueue.main.async { [weak self] in self?.addToPreviewStream?(CIImage(cvPixelBuffer: pixelBuffer)) } } }
- 修复start方法的异步捕获问题
用[weak self]避免循环引用,同时确保所有session相关操作都在sessionQueue内执行:
func start() async { let authorized = await checkAuthorization() guard authorized else { logger.error("Camera access was not authorized.") return } sessionQueue.async { [weak self] in guard let self = self else { return } if self.isCaptureSessionConfigured { if !self.captureSession.isRunning { self.captureSession.startRunning() } return } self.configureCaptureSession { success in guard success else { return } self.captureSession.startRunning() } } }
- 确保属性访问的线程一致性
所有对captureSession、deviceInput等属性的读写操作,必须统一在sessionQueue内执行,避免跨线程未同步访问导致的数据竞争。
关键规则回顾
AVCaptureSession的所有操作(配置、启动/停止、输入输出添加、连接修改)必须在同一个串行队列执行,Swift 6严格并发会把之前隐式的线程安全问题暴露为崩溃,因此必须显式保证操作的线程一致性。
内容的提问来源于stack exchange,提问作者miltenkot
相关产品推荐
相关产品推荐

