SwiftUI如何从UIKit获取数据到SwiftUI

4

我正在为我的应用程序构建一个条形码阅读器,目前我可以获取值,但无法将数据传递给我的SwiftUI应用程序。应用程序的阅读器部分使用UIKit,我使用Firebase ML条形码阅读器。在SwiftUI部分中似乎找不到任何获取卡片编号的方法。当条形码解码完成后,我还想关闭视图。感谢您的帮助。

这是我的条形码阅读器文件:

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个回答

1
这是一个可能的方法。
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
                    }
                }
            }
        }    
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接