【问题标题】:Enabling rescanning QRCode after successful scan扫描成功后启用扫描二维码
【发布时间】:2022-07-22 07:54:55
【问题描述】:

我根据这篇文章创建了二维码扫描器-https://blog.devgenius.io/camera-preview-and-a-qr-code-scanner-in-swiftui-48b111155c66

程序正常执行,扫描成功后,sheet 会打开,其中包含来自 QRCode 的详细信息。但问题是,在关闭工作表后,我想再次启用重新扫描,而不是重新启动应用程序再次扫描(这是现在的问题。)

QRCodeScannerView 委托

struct QrCodeScannerView: UIViewRepresentable {

let isScanning: Bool

init(isScanning: Bool){
    self.isScanning = isScanning
}

var supportedBarcodeTypes: [AVMetadataObject.ObjectType] = [.qr]
typealias UIViewType = CameraPreview
private let session = AVCaptureSession()
private let delegate = QrCodeCameraDelegate()
private let metadataOutput = AVCaptureMetadataOutput()

func torchLight(isOn: Bool) -> QrCodeScannerView {
    if let backCamera = AVCaptureDevice.default(for: AVMediaType.video) {
        if backCamera.hasTorch {
            try? backCamera.lockForConfiguration()
            if isOn {
                backCamera.torchMode = .on
            } else {
                backCamera.torchMode = .off
            }
            backCamera.unlockForConfiguration()
        }
    }
    return self
}

func interval(delay: Double) -> QrCodeScannerView {
    delegate.scanInterval = delay
    return self
}

func found(r: @escaping (String) -> Void) -> QrCodeScannerView {
    delegate.onResult = r
    return self
}

func simulator(mockBarCode: String)-> QrCodeScannerView{
    delegate.mockData = mockBarCode
    return self
}

func setupCamera(_ uiView: CameraPreview) {
    if let backCamera = AVCaptureDevice.default(for: AVMediaType.video) {
        if let input = try? AVCaptureDeviceInput(device: backCamera) {
            session.sessionPreset = .photo
            
            if session.canAddInput(input) {
                session.addInput(input)
            }
            if session.canAddOutput(metadataOutput) {
                session.addOutput(metadataOutput)
                
                metadataOutput.metadataObjectTypes = supportedBarcodeTypes
                metadataOutput.setMetadataObjectsDelegate(delegate, queue: DispatchQueue.main)
            }
            let previewLayer = AVCaptureVideoPreviewLayer(session: session)
            
            uiView.backgroundColor = UIColor.gray
            previewLayer.videoGravity = .resizeAspectFill
            uiView.layer.addSublayer(previewLayer)
            uiView.previewLayer = previewLayer
            
            session.startRunning()
        }
    }
}

func makeUIView(context: UIViewRepresentableContext<QrCodeScannerView>) -> QrCodeScannerView.UIViewType {
    let cameraView = CameraPreview(session: session)
        
    #if targetEnvironment(simulator)
            cameraView.createSimulatorView(delegate: self.delegate)
    #else
            checkCameraAuthorizationStatus(cameraView)
    #endif
        
    return cameraView
}

private func checkCameraAuthorizationStatus(_ uiView: CameraPreview) {
    let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
    if cameraAuthorizationStatus == .authorized {
        setupCamera(uiView)
    } else {
        AVCaptureDevice.requestAccess(for: .video) { granted in
            DispatchQueue.main.sync {
                if granted {
                    self.setupCamera(uiView)
                }
            }
        }
    }
}

func updateUIView(_ uiView: CameraPreview, context: UIViewRepresentableContext<QrCodeScannerView>) {
    uiView.setContentHuggingPriority(.defaultHigh, for: .vertical)
    uiView.setContentHuggingPriority(.defaultLow, for: .horizontal)
    
    if isScanning {
        session.startRunning()
    } else {
        session.stopRunning()
    }
}
}

我的看法

var body: some View {
    ZStack {
        QrCodeScannerView(isScanning: viewModel.isScanning)
            .found(r: self.viewModel.scanCertificate)
            .torchLight(isOn: self.viewModel.torchIsOn)
            .interval(delay: self.viewModel.scanInterval)
        
        VStack {
            Spacer()
            HStack {
                Button(action: {
                    self.viewModel.torchIsOn.toggle()
                }, label: {
                    Image(systemName: self.viewModel.torchIsOn ? "bolt.fill" : "bolt.slash.fill")
                        .imageScale(.large)
                        .foregroundColor(self.viewModel.torchIsOn ? Color.yellow : Color.blue)
                        .padding()
                })
            }
            .background(Color.white)
            .cornerRadius(10)
        }
        .sheet(isPresented: $viewModel.isScanned) {
            details()
        }
        .sheet(isPresented: $viewModel.isError) {
            alert()
        }
        .padding()
    }
}

工作表视图

@ViewBuilder
private func alert() -> some View {
    let screen = UIScreen.main.bounds
    
    VStack {
        Spacer()
        
        Text("Error while validating QR Code.")
            .commonFont(.bold, style: .body)
            .padding()
        
        HStack {
            Button {
                print("")
            } label: {
                Text("Scan again")
            }
            .frame(width: screen.width * 0.35)
            .coronaVirusAppButtonStyle()
            
            Button {
                print("")
            } label: {
                Text("Back")
            }
            .frame(width: screen.width * 0.35)
            .coronaVirusAppButtonStyle()
        }
        
        Spacer()
    }
    .padding()
    .onAppear {
        viewModel.isScanning = false
    }
    .onDisappear {
        viewModel.isScanning = true
    }
}

我在 QrCodeScannerView isScanning 中创建了属性,updateView 会话中的哪个值将进入 startRunningstopRunning

在 MyView 中,我在工作表 hasAppeared 时将 isScanning 设置为 false 以停止摄像头,当工作表 hasDisappeared 将 isScanning 设置为 true 以启动摄像头时,但这是效果不好..

【问题讨论】:

    标签: swift


    【解决方案1】:

    您找到解决此问题的方法了吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-15
      相关资源
      最近更新 更多