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