Enhance ScannerViewModel to improve camera permission handling and capture session setup. Update logging messages for clarity and add retry logic for starting the scanning session. Ensure immediate scanning initiation after session setup, enhancing user experience and reliability.

main
v504 2 months ago
parent 81b2c74846
commit c350669bba

@ -27,9 +27,10 @@ class ScannerViewModel: NSObject, ObservableObject, AVCaptureMetadataOutputObjec
switch AVCaptureDevice.authorizationStatus(for: .video) { switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized: case .authorized:
logInfo("✅ 相机权限已授权", className: "ScannerViewModel") logInfo("✅ 相机权限已授权,立即设置捕获会话", className: "ScannerViewModel")
cameraAuthorizationStatus = .authorized cameraAuthorizationStatus = .authorized
setupCaptureSession() setupCaptureSession()
// setupCaptureSession
case .notDetermined: case .notDetermined:
logInfo("❓ 相机权限未确定,请求权限", className: "ScannerViewModel") logInfo("❓ 相机权限未确定,请求权限", className: "ScannerViewModel")
@ -51,9 +52,10 @@ class ScannerViewModel: NSObject, ObservableObject, AVCaptureMetadataOutputObjec
AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
DispatchQueue.main.async { DispatchQueue.main.async {
if granted { if granted {
logInfo("✅ 相机权限请求成功", className: "ScannerViewModel") logInfo("✅ 相机权限请求成功,立即设置捕获会话", className: "ScannerViewModel")
self?.cameraAuthorizationStatus = .authorized self?.cameraAuthorizationStatus = .authorized
self?.setupCaptureSession() self?.setupCaptureSession()
// setupCaptureSession
} else { } else {
logWarning("❌ 相机权限请求被拒绝", className: "ScannerViewModel") logWarning("❌ 相机权限请求被拒绝", className: "ScannerViewModel")
self?.cameraAuthorizationStatus = .denied self?.cameraAuthorizationStatus = .denied
@ -78,15 +80,25 @@ class ScannerViewModel: NSObject, ObservableObject, AVCaptureMetadataOutputObjec
func refreshCameraPermission() { func refreshCameraPermission() {
logInfo("🔍 重新检查相机权限状态", className: "ScannerViewModel") logInfo("🔍 重新检查相机权限状态", className: "ScannerViewModel")
//
if captureSession?.isRunning == true {
stopScanning()
}
//
checkCameraPermission() checkCameraPermission()
} }
// MARK: - // MARK: -
private func setupCaptureSession() { private func setupCaptureSession() {
logInfo("🔧 开始设置捕获会话", className: "ScannerViewModel")
captureSession = AVCaptureSession() captureSession = AVCaptureSession()
guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else { guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else {
logError("❌ 无法获取视频设备", className: "ScannerViewModel")
showAlert = true showAlert = true
return return
} }
@ -99,13 +111,16 @@ class ScannerViewModel: NSObject, ObservableObject, AVCaptureMetadataOutputObjec
do { do {
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice) videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
} catch { } catch {
logError("❌ 创建视频输入失败: \(error.localizedDescription)", className: "ScannerViewModel")
showAlert = true showAlert = true
return return
} }
if captureSession.canAddInput(videoInput) { if captureSession.canAddInput(videoInput) {
captureSession.addInput(videoInput) captureSession.addInput(videoInput)
logInfo("✅ 成功添加视频输入", className: "ScannerViewModel")
} else { } else {
logError("❌ 无法添加视频输入", className: "ScannerViewModel")
showAlert = true showAlert = true
return return
} }
@ -117,10 +132,19 @@ class ScannerViewModel: NSObject, ObservableObject, AVCaptureMetadataOutputObjec
captureSession.addOutput(metadataOutput) captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main) metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = [.qr, .ean8, .ean13, .code128, .code39, .upce, .pdf417, .aztec] metadataOutput.metadataObjectTypes = [.qr, .ean8, .ean13, .code128, .code39, .upce, .pdf417, .aztec]
logInfo("✅ 成功添加元数据输出", className: "ScannerViewModel")
} else { } else {
logError("❌ 无法添加元数据输出", className: "ScannerViewModel")
showAlert = true showAlert = true
return return
} }
logInfo("✅ 捕获会话设置完成,准备启动扫描", className: "ScannerViewModel")
//
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
self?.startScanning()
}
} }
// MARK: - // MARK: -
@ -128,23 +152,70 @@ class ScannerViewModel: NSObject, ObservableObject, AVCaptureMetadataOutputObjec
func startScanning() { func startScanning() {
logInfo("🔄 开始扫描", className: "ScannerViewModel") logInfo("🔄 开始扫描", className: "ScannerViewModel")
//
guard cameraAuthorizationStatus == .authorized else {
logWarning("❌ 相机权限未授权,无法启动扫描", className: "ScannerViewModel")
return
}
//
guard captureSession != nil else {
logWarning("⚠️ 捕获会话未设置,重新设置", className: "ScannerViewModel")
setupCaptureSession()
return
}
// //
if captureSession?.isRunning == true { if captureSession.isRunning {
logInfo(" 扫描会话已经在运行", className: "ScannerViewModel") logInfo(" 扫描会话已经在运行", className: "ScannerViewModel")
return return
} }
//
if captureSession.inputs.isEmpty || captureSession.outputs.isEmpty {
logWarning("⚠️ 捕获会话配置不完整,重新设置", className: "ScannerViewModel")
setupCaptureSession()
return
}
logInfo("🚀 启动扫描会话", className: "ScannerViewModel")
DispatchQueue.global(qos: .userInitiated).async { [weak self] in DispatchQueue.global(qos: .userInitiated).async { [weak self] in
guard let self = self else { return } guard let self = self else { return }
self.captureSession?.startRunning() self.captureSession?.startRunning()
// //
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
if self.captureSession?.isRunning == true { if self.captureSession?.isRunning == true {
logInfo("✅ 扫描会话启动成功", className: "ScannerViewModel") logInfo("✅ 扫描会话启动成功", className: "ScannerViewModel")
} else { } else {
logWarning("⚠️ 扫描会话启动失败", className: "ScannerViewModel") logWarning("⚠️ 扫描会话启动失败,尝试重试", className: "ScannerViewModel")
//
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.retryStartScanning()
}
}
}
}
}
private func retryStartScanning() {
logInfo("🔄 重试启动扫描", className: "ScannerViewModel")
guard captureSession != nil else {
logError("❌ 捕获会话为空,无法重试", className: "ScannerViewModel")
return
}
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
self?.captureSession?.startRunning()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
if self?.captureSession?.isRunning == true {
logInfo("✅ 重试启动扫描成功", className: "ScannerViewModel")
} else {
logError("❌ 重试启动扫描失败", className: "ScannerViewModel")
} }
} }
} }

Loading…
Cancel
Save