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

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]的有效范围
  • 相机设备状态异常(如被其他会话占用、设备断开),导致配置锁失效后仍执行参数设置

修复方案

针对上述可能的原因,对代码进行以下优化:

  1. 校验设备能力:设置参数前先确认设备是否支持对应功能
  2. 限制坐标范围:确保对焦坐标始终在0到1的有效区间内
  3. 确保配置锁正确释放:使用defer语句保证锁一定会被释放
  4. 捕获参数设置异常:对设备参数设置过程添加异常捕获,避免崩溃

修改后的代码

/** 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:35:09