4

I'm building a BarCode reader into my app, so far I can have the value but I can't pass the data to my SwiftUI App. The reader part of the app uses UIKit, I use firebase ml barcode reader. I can't seem to find any way to get the number of the card in the SwiftUI part. I also want to dismiss the view when the barcode has been decoded. Thanks for the help.

Here is the File of my Barcode reader :

import SwiftUI
import UIKit
import AVFoundation
import Firebase

struct BarcodeView: View {
    
    @State var isShowingCameraView = false
    
    var body: some View {
        CameraView()
            .edgesIgnoringSafeArea(.all)
        Text("Here I want to have the barcode number")

    }
}

struct BarcodeView_Previews: PreviewProvider {
    static var previews: some View {
        BarcodeView()
    }
}

//UIKit

struct CameraView : UIViewControllerRepresentable {
    
    let myBarcode: Int = 0
    
    
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<CameraView>) -> UIViewController {
        let controller = BarCodeDetectorViewController()
        return controller
    }
    
    func updateUIViewController(_ uiViewController: CameraView.UIViewControllerType, context: UIViewControllerRepresentableContext<CameraView>) {}
}

class BarCodeDetectorViewController : UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {

    let session = AVCaptureSession()
    lazy var vision = Vision.vision()
    var barcodeDetector :VisionBarcodeDetector?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        startLiveVideo()
        self.barcodeDetector = vision.barcodeDetector()
    }
    
    func startLiveVideo() {
        
        session.sessionPreset = AVCaptureSession.Preset.photo
        let captureDevice = AVCaptureDevice.default(for: AVMediaType.video)
                
        let deviceInput = try! AVCaptureDeviceInput(device: captureDevice!)
        let deviceOutput = AVCaptureVideoDataOutput()
        deviceOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32BGRA)]
        deviceOutput.setSampleBufferDelegate(self, queue: DispatchQueue.global(qos: DispatchQoS.QoSClass.default))
        session.addInput(deviceInput)
        session.addOutput(deviceOutput)

        let cameraPreview = AVCaptureVideoPreviewLayer(session: session)
                        
        view.layer.addSublayer(cameraPreview)
        cameraPreview.frame = view.frame

        session.startRunning()
    }
    
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
            
            if let barcodeDetector = self.barcodeDetector {
                
                let visionImage = VisionImage(buffer: sampleBuffer)
                
                barcodeDetector.detect(in: visionImage) { (barcodes, error) in
                    
                    if let error = error {
                        print(error.localizedDescription)
                        return
                    }
                    
                    for barcode in barcodes! {
                        print(barcode.rawValue!) //here is the card number
                    }
                }
            }
        }    
}

1 Answer 1

1

Here is possible approach

class BarCodeViewModel: ObservableObject {
   @Published var cardNumber: String = ""
}

struct BarcodeView: View {
    @ObservedObject var vm = BarCodeViewModel()

    @State var isShowingCameraView = false
    
    var body: some View {
        CameraView(model: vm)
            .edgesIgnoringSafeArea(.all)
        Text(vm.cardNumber)

    }
}

struct BarcodeView_Previews: PreviewProvider {
    static var previews: some View {
        BarcodeView()
    }
}

//UIKit

struct CameraView : UIViewControllerRepresentable {
    let model: BarCodeViewModel
    let myBarcode: Int = 0
    
    
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<CameraView>) -> UIViewController {
        let controller = BarCodeDetectorViewController()
        controller.bridgeModel = self.model
        return controller
    }
    
    func updateUIViewController(_ uiViewController: CameraView.UIViewControllerType, context: UIViewControllerRepresentableContext<CameraView>) {}
}

class BarCodeDetectorViewController : UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {

    let session = AVCaptureSession()
    lazy var vision = Vision.vision()
    var barcodeDetector :VisionBarcodeDetector?
    var bridgeModel: BarCodeViewModel?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        startLiveVideo()
        self.barcodeDetector = vision.barcodeDetector()
    }
    
    func startLiveVideo() {
        
        session.sessionPreset = AVCaptureSession.Preset.photo
        let captureDevice = AVCaptureDevice.default(for: AVMediaType.video)
                
        let deviceInput = try! AVCaptureDeviceInput(device: captureDevice!)
        let deviceOutput = AVCaptureVideoDataOutput()
        deviceOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32BGRA)]
        deviceOutput.setSampleBufferDelegate(self, queue: DispatchQueue.global(qos: DispatchQoS.QoSClass.default))
        session.addInput(deviceInput)
        session.addOutput(deviceOutput)

        let cameraPreview = AVCaptureVideoPreviewLayer(session: session)
                        
        view.layer.addSublayer(cameraPreview)
        cameraPreview.frame = view.frame

        session.startRunning()
    }
    
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
            
            if let barcodeDetector = self.barcodeDetector {
                
                let visionImage = VisionImage(buffer: sampleBuffer)
                
                barcodeDetector.detect(in: visionImage) { (barcodes, error) in
                    
                    if let error = error {
                        print(error.localizedDescription)
                        return
                    }
                    
                    for barcode in barcodes! {
                        print(barcode.rawValue!) //here is the card number
                    }

                    DispatchQueue.main.async {
                       self.bridgeModel.cardNumber = ... // << assign here as needed
                    }
                }
            }
        }    
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.