Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI getting data from UIKit to SwiftUI

Tags:

swiftui

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
                    }
                }
            }
        }    
}
like image 370
MaxBrt18 Avatar asked Dec 02 '25 10:12

MaxBrt18


1 Answers

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
                    }
                }
            }
        }    
}
like image 158
Asperi Avatar answered Dec 05 '25 08:12

Asperi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!