iOS扫码App触摸屏幕触发自动对焦时偶现崩溃求助
相机扫码触摸对焦偶发崩溃问题排查与解决
我的App实现了触摸屏幕对应位置自动对焦的二维码扫描功能,但偶发崩溃,崩溃点在device.focusPointOfInterest = focusPoint这一行。
相关代码
/** Touch the screen for autofocus */ public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { guard touches.first?.view == view, let touchPoint = touches.first, let device = videoCaptureDevice else { return } let videoView = view let screenSize = videoView!.bounds.size let xPoint = touchPoint.location(in: videoView).y / screenSize.height let yPoint = 1.0 - touchPoint.location(in: videoView).x / screenSize.width let focusPoint = CGPoint(x: xPoint, y: yPoint) do { try device.lockForConfiguration() } catch { return } // Focus to the correct point, make continiuous focus and exposure so the point stays sharp when moving the device closer device.focusPointOfInterest = focusPoint device.focusMode = .continuousAutoFocus device.exposurePointOfInterest = focusPoint device.exposureMode = AVCaptureDevice.ExposureMode.continuousAutoExposure device.unlockForConfiguration() }
崩溃日志(相关部分)
Last Exception Backtrace: 0 CoreFoundation 0x180f37c60 __exceptionPreprocess + 216 (NSException.m:200) 1 libobjc.A.dylib 0x198767ee4 objc_exception_throw + 56 (objc- exception.mm:565) 2 AVFCapture 0x1a45297f4 -[AVCaptureFigVideoDevice setFocusPointOfInterest:] + 276 (AVCaptureFigVideoDevice.m:0) 3 QR Code Creator Scanner 0x1021f13bc specialized CodeScannerView.ScannerViewController.touchesBegan(_:with:) + 508 (CodeScannerView.swift:307) 4 QR Code Creator Scanner 0x1021f010c CodeScannerView.ScannerViewController.touchesBegan(_:with:) + 12 (<compiler- generated>:0) 5 QR Code Creator Scanner 0x1021f010c @objc CodeScannerView.ScannerViewController.touchesBegan(_:with:) + 120 6 UIKitCore 0x1833c099c forwardTouchMethod + 316 (UIResponder.m:2039) 7 UIKitCore 0x183341ed0 -[UIWindow _sendTouchesForEvent:] + 624 (UIWindow.m:2960)
崩溃原因分析
从崩溃栈可以看出,异常来自AVFoundation框架的setFocusPointOfInterest:方法,可能的触发场景包括:
- 设备不支持手动指定对焦兴趣点(比如部分老旧设备或前置摄像头)
- 计算出的对焦坐标超出了[0,1]的有效范围
- 相机设备状态异常(如被其他会话占用、设备断开),导致配置锁失效后仍执行参数设置
修复方案
针对上述可能的原因,对代码进行以下优化:
- 校验设备能力:设置参数前先确认设备是否支持对应功能
- 限制坐标范围:确保对焦坐标始终在0到1的有效区间内
- 确保配置锁正确释放:使用
defer语句保证锁一定会被释放 - 捕获参数设置异常:对设备参数设置过程添加异常捕获,避免崩溃
修改后的代码
/** Touch the screen for autofocus */ public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { guard touches.first?.view == view, let touchPoint = touches.first, let device = videoCaptureDevice else { return } let videoView = view let screenSize = videoView!.bounds.size let rawX = touchPoint.location(in: videoView).y / screenSize.height let rawY = 1.0 - touchPoint.location(in: videoView).x / screenSize.width // 限制坐标在[0,1]有效范围内 let xPoint = max(0.0, min(1.0, rawX)) let yPoint = max(0.0, min(1.0, rawY)) let focusPoint = CGPoint(x: xPoint, y: yPoint) do { try device.lockForConfiguration() } catch { return } // 确保无论是否异常,都会释放配置锁 defer { device.unlockForConfiguration() } do { // 检查对焦功能支持性 if device.isFocusPointOfInterestSupported, device.isFocusModeSupported(.continuousAutoFocus) { device.focusPointOfInterest = focusPoint device.focusMode = .continuousAutoFocus } // 检查曝光功能支持性 if device.isExposurePointOfInterestSupported, device.isExposureModeSupported(.continuousAutoExposure) { device.exposurePointOfInterest = focusPoint device.exposureMode = .continuousAutoExposure } } catch { print("相机配置设置失败: \(error)") } }
补充说明
- 部分设备的前置摄像头或老旧机型不支持手动对焦,必须通过能力校验避免无效操作
- 坐标范围限制可以解决因视图边界计算误差、触摸位置超出视图等情况导致的无效坐标输入
defer语句能保证设备配置锁被正确释放,避免因异常导致锁未释放,影响后续相机操作
内容的提问来源于stack exchange,提问作者Deepak Gautam
相关产品推荐
相关产品推荐

