diff --git a/suixinkan/UI/Scan/QRCodeScannerViewController.swift b/suixinkan/UI/Scan/QRCodeScannerViewController.swift index fc10291..54c38e4 100644 --- a/suixinkan/UI/Scan/QRCodeScannerViewController.swift +++ b/suixinkan/UI/Scan/QRCodeScannerViewController.swift @@ -14,6 +14,7 @@ final class QRCodeScannerViewController: BaseViewController, AVCaptureMetadataOu private let captureSession = AVCaptureSession() private var previewLayer: AVCaptureVideoPreviewLayer? + private var isCameraConfigured = false private var hasHandledResult = false private let maskView = UIView() @@ -60,17 +61,21 @@ final class QRCodeScannerViewController: BaseViewController, AVCaptureMetadataOu checkCameraPermission() } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + updatePreviewLayout() + startCaptureSessionIfNeeded() + } + override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() - previewLayer?.frame = view.bounds + updatePreviewLayout() updateMask() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - if captureSession.isRunning { - captureSession.stopRunning() - } + stopCaptureSession() } private func checkCameraPermission() { @@ -94,11 +99,21 @@ final class QRCodeScannerViewController: BaseViewController, AVCaptureMetadataOu } private func setupCamera() { + if isCameraConfigured { + updatePreviewLayout() + startCaptureSessionIfNeeded() + return + } + guard let device = AVCaptureDevice.default(for: .video), let input = try? AVCaptureDeviceInput(device: device) else { showToast("无法打开相机") return } + + captureSession.beginConfiguration() + defer { captureSession.commitConfiguration() } + guard captureSession.canAddInput(input) else { return } captureSession.addInput(input) @@ -112,12 +127,30 @@ final class QRCodeScannerViewController: BaseViewController, AVCaptureMetadataOu layer.videoGravity = .resizeAspectFill view.layer.insertSublayer(layer, at: 0) previewLayer = layer + isCameraConfigured = true + updatePreviewLayout() + startCaptureSessionIfNeeded() + } + + private func updatePreviewLayout() { + previewLayer?.frame = view.bounds + } + + private func startCaptureSessionIfNeeded() { + guard isCameraConfigured, !captureSession.isRunning else { return } DispatchQueue.global(qos: .userInitiated).async { [weak self] in self?.captureSession.startRunning() } } + private func stopCaptureSession() { + guard captureSession.isRunning else { return } + DispatchQueue.global(qos: .userInitiated).async { [weak self] in + self?.captureSession.stopRunning() + } + } + private func updateMask() { maskView.layer.sublayers?.forEach { $0.removeFromSuperlayer() } let border = CAShapeLayer() @@ -139,7 +172,7 @@ final class QRCodeScannerViewController: BaseViewController, AVCaptureMetadataOu let value = object.stringValue, !value.isEmpty else { return } hasHandledResult = true - captureSession.stopRunning() + stopCaptureSession() onScanResult?(value) dismiss(animated: true) }