You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 6下AVCaptureSession启动崩溃问题求助

Swift 6 下 AVCaptureSession 崩溃问题修复方案

核心问题分析

崩溃源于Swift 6严格并发模式下,AVCaptureSession相关操作的线程安全违规和Actor隔离冲突,具体体现在代理方法的线程切换错误、属性跨线程未同步访问、以及Sendable合规性缺失。

具体修复步骤

  1. 确保类遵循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
    // 其他属性和方法...
}
  1. 修正代理方法的线程逻辑
    你给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))
        }
    }
}
  1. 修复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()
        }
    }
}
  1. 确保属性访问的线程一致性
    所有对captureSession、deviceInput等属性的读写操作,必须统一在sessionQueue内执行,避免跨线程未同步访问导致的数据竞争。

关键规则回顾

AVCaptureSession的所有操作(配置、启动/停止、输入输出添加、连接修改)必须在同一个串行队列执行,Swift 6严格并发会把之前隐式的线程安全问题暴露为崩溃,因此必须显式保证操作的线程一致性。

内容的提问来源于stack exchange,提问作者miltenkot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 01:01:02