升级iOS 18后AVCapturePhotoCaptureDelegate报sessionNotRunning错误
问题背景
我的相机捕获代码在iOS 18之前运行完全正常,封装拍照功能的PhotoCaptureManager类会在用户进入相机界面时懒加载初始化AVCaptureSession,在CameraViewController的viewDidAppear中启动会话,点击拍照按钮执行捕获逻辑。但升级到iOS 18后,点击拍照会抛出AVError.Code.sessionNotRunning错误,尽管captureSession.isRunning始终返回true,且photoOutput.captureReadiness状态为.ready。
相关代码片段
初始化 AVCaptureSession
lazy var captureSession: AVCaptureSession? = { let session = AVCaptureSession() session.automaticallyConfiguresApplicationAudioSession = false do { guard let videoDevice = self.currentVideoDevice else { return nil } let videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice) guard session.canAddInput(videoDeviceInput) else { return nil} session.beginConfiguration() session.addInput(videoDeviceInput) session.addOutput(photoOutput) session.sessionPreset = .photo session.commitConfiguration() return session } catch { print(error) return nil } }()
启动会话的逻辑
private func setupCameraPreview() { DispatchQueue.main.async { self.cameraPreview.videoPreviewLayer.session = self.cameraManager.capture.captureSession DispatchQueue.global(qos: .userInteractive).async { [weak self] in self?.cameraManager.capture.captureSession?.startRunning() } } }
拍照触发逻辑
func takePicture(_ completion: @escaping (_ imageData: Data?) -> Void) { takePictureCompletion = completion let settings = AVCapturePhotoSettings() photoOutput.connection(with: AVMediaType.video)?.videoOrientation = currentVideoOrientation(by: UIDevice.current.orientation) photoOutput.capturePhoto(with: settings, delegate: self) }
捕获结果处理
extension DefaultPhotoCaptureManager: AVCapturePhotoCaptureDelegate { func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { if let error { print(error) return } guard let jpegData = photo.fileDataRepresentation() else { return } takePictureCompletion?(jpegData) } func photoOutput(_ output: AVCapturePhotoOutput, didCapturePhotoFor resolvedSettings: AVCaptureResolvedPhotoSettings) { print(resolvedSettings) } }
错误信息
执行拍照时,didCapturePhotoFor方法打印的日志:
<<<< AVCapturePhotoOutput >>>> Fig assert: "hasFigCaptureSession" at bail (AVCapturePhotoOutput.m:529) - (err=0)
<AVCaptureResolvedPhotoSettings: 0x30163d4a0 uid:3 photo:{0x0} time:nan-nan>
didFinishProcessingPhoto返回的错误详情:
Optional
- some : Error Domain=AVFoundationErrorDomain Code=-11803 UserInfo={AVErrorRecordingFailureDomainKey=3}
对应的错误码为AVError.Code.sessionNotRunning,但多次检查确认captureSession.isRunning为true,photoOutput.captureReadiness始终是.ready。
临时解决方案
在takePicture方法中添加iOS 18专属适配代码后,问题得到解决:
if #available(iOS 18.0, *) { photoOutput.maxPhotoQualityPrioritization = .speed }
根据官方文档说明,运行时修改maxPhotoQualityPrioritization属性会触发会话重建,可能导致预览中断,但实际测试中并未出现预览中断的情况,反而解决了拍照报错的问题。
疑问
想知道iOS 18中引发这个问题的具体原因是什么?是否有其他开发者遇到过相同的问题?
内容的提问来源于stack exchange,提问作者Alex Sh.

