如何处理photoOutput(_:didFinishProcessingPhoto:error:)的错误及复现相机故障
关于AVCapturePhotoOutput错误处理及故障复现的解决方案
一、错误合理处理方案
- 先对错误做分类处理,不要统一逻辑响应:首先把error转为
AVCaptureError枚举匹配错误码,区分错误类型再处理- 若匹配到
AVCaptureError.Code.clientIsNotAuthorized这类权限相关错误,直接判定为用户失去相机权限,弹出引导提示告知用户到系统设置开启权限,无需重启会话 - 若匹配到
AVCaptureError.Code.sessionWasInterrupted、AVCaptureError.Code.deviceIsNotAvailable等会话中断、硬件不可用类错误,优先重启capture session:标准流程为先调用session.stopRunning(),移除当前所有input、output,重置session预设值,再按初始化流程重新配置输入输出后调用startRunning(),90%以上的临时硬件冲突、会话中断导致的黑屏、无法拍摄问题都可通过该方案解决 - 若连续2次重启session后仍然触发相同错误,弹出用户友好提示「相机暂时无法使用,请重启应用后重试」,同时把错误栈、设备信息、系统版本上报到埋点系统,方便后续定位特殊问题
- 若匹配到
- 不要无差别将错误判定为权限丢失,线上绝大多数偶发拍摄错误都来自系统相机调度冲突、会话临时中断,重启会话即可恢复
优化后代码示例
// 类内部声明重试计数变量 private var restartSessionRetryCount = 0 func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { // ... if let error = error as? NSError { print("Error capturing photo: \(error)") // 上报错误到业务埋点 reportCameraError(error) switch AVCaptureError.Code(rawValue: error.code) { case .clientIsNotAuthorized: // 跳转权限引导逻辑 showPermissionAlert() return default: // 加重试次数限制,避免短时间无限重启 if restartSessionRetryCount < 2 { restartCaptureSession() restartSessionRetryCount += 1 } else { showCameraFailureTip() } return } } // 拍摄正常时重置重试计数 restartSessionRetryCount = 0 // 正常处理照片逻辑 // ... }
二、相机硬件类故障复现方法
- 复现会话中断类故障:拍摄过程中快速切换应用前后台,或者拍摄过程中从控制中心点击手电筒、扫码等呼起系统相机占用硬件的功能,再快速切回你的应用,大概率可以复现session中断导致的拍摄错误、黑屏问题
- 复现硬件占用冲突故障:先打开系统相机保持前台运行,再通过多任务快速切到你的应用点击拍摄,很容易触发硬件占用类的拍摄错误
- 复现极端场景故障:在低内存设备上(或者打开Xcode的低内存模拟开关)同时运行3个以上需要调用相机、麦克风的应用,再发起拍摄,即可复现系统资源不足导致的偶发拍摄错误
- 以上场景触发的错误就是线上用户遇到的绝大多数真实硬件类故障,不需要实际损坏硬件即可验证修复逻辑有效性
内容的提问来源于stack exchange,提问作者timbre timbre
相关产品推荐
相关产品推荐

