如何将扫描的条形码 ID 从第一个视图控制器传递到第二个视图控制器的 UILabel?

How do I pass a scanned barcode ID from first view controller to second View Controller's UILabel?

这是我在程序中使用的条码扫描教程,让你在阅读我的代码时有更多的上下文:Link

这是我的程序到目前为止所做的事情:本质上,当我用我的 phone 扫描项目的条形码时,UIAlert 会弹出并显示条形码 ID 和一个按钮,提示用户打开“结果” “ 页。这一切都很好,但是如何将相同的扫描条形码 ID 传递到结果页面 上的标签中?我已经坚持了 2 天了,尽管这看起来很容易。

非常感谢任何帮助<3

这是我的相关代码:

ProductCatalog.plist -> Link to Image

Scanner_ViewController.swift(第一个视图控制器)->

import UIKit
import AVFoundation

class Scanner_ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate, ScannerDelegate
{
    private var scanner: Scanner?

    override func viewDidLoad()
    {
        super.viewDidLoad()
    
        self.scanner = Scanner(withDelegate: self)
    
        guard let scanner = self.scanner else
        {
            return
        }
    
        scanner.requestCaptureSessionStartRunning()
    }

    override func didReceiveMemoryWarning()
    {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // Mark - AVFoundation delegate methods
    public func metadataOutput(_ output: AVCaptureMetadataOutput,
                               didOutput metadataObjects: [AVMetadataObject],
                               from connection: AVCaptureConnection)
    {
        guard let scanner = self.scanner else
        {
            return
        }
        scanner.metadataOutput(output,
                               didOutput: metadataObjects,
                               from: connection)
    }

    // Mark - Scanner delegate methods
    func cameraView() -> UIView
    {
        return self.view
    } 

    func delegateViewController() -> UIViewController
    {
        return self
    }

    func scanCompleted(withCode code: String)
    {
        print(code)
        showAlert_Success(withTitle: (code))
    }
 
    private func showAlert_Success(withTitle title: String)
    {
        let alertController = UIAlertController(title: title, message: "Product has been successfully scanned", preferredStyle: .alert)

        // programatically segue to the next view controller when the UIAlert pops up
        alertController.addAction(UIAlertAction(title:"Get Results", style: .default, handler:{ action in self.performSegue(withIdentifier: "toAnalysisPage", sender: self) }))
    
        present(alertController, animated: true)
    }
}

Scanner.Swift(伴随Scanner_ViewController.swift)->

import Foundation
import UIKit
import AVFoundation

protocol ScannerDelegate: class
{
    func cameraView() -> UIView
    func delegateViewController() -> UIViewController
    func scanCompleted(withCode code: String)
}

class Scanner: NSObject
{
    public weak var delegate: ScannerDelegate?
    private var captureSession : AVCaptureSession?

    init(withDelegate delegate: ScannerDelegate)
    {
        self.delegate = delegate
        super.init()
        self.scannerSetup()
    }

    private func scannerSetup()
    {
        guard let captureSession = self.createCaptureSession()
    
        else
        {
            return
        }
    
        self.captureSession = captureSession
    
        guard let delegate = self.delegate
    
        else
        {
            return
        }
    
        let cameraView = delegate.cameraView()
        let previewLayer = self.createPreviewLayer(withCaptureSession: captureSession,
                                                   view: cameraView)
        cameraView.layer.addSublayer(previewLayer)
    }

    private func createCaptureSession() -> AVCaptureSession?
    {
        do
        {
            let captureSession = AVCaptureSession()
            guard let captureDevice = AVCaptureDevice.default(for: .video) else
            {
            return nil
            }
        
            let deviceInput = try AVCaptureDeviceInput(device: captureDevice)
            let metaDataOutput = AVCaptureMetadataOutput()
        
            // add device input
            if captureSession.canAddInput(deviceInput) && captureSession.canAddOutput(metaDataOutput)
            {
                captureSession.addInput(deviceInput)
                captureSession.addOutput(metaDataOutput)
            
                guard let delegate = self.delegate,
                    let viewController = delegate.delegateViewController() as? AVCaptureMetadataOutputObjectsDelegate else
                {
                        return nil
                }
            
                metaDataOutput.setMetadataObjectsDelegate(viewController,
                                                          queue: DispatchQueue.main)
                metaDataOutput.metadataObjectTypes = self.metaObjectTypes()
             
                return captureSession
            }
        }
    
        catch
        {
            // handle error
        }
    
        return nil
    }

    private func createPreviewLayer(withCaptureSession captureSession: AVCaptureSession,
                                    view: UIView) -> AVCaptureVideoPreviewLayer
    {
        let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer.frame = view.layer.bounds
        previewLayer.videoGravity = .resizeAspectFill
    
        return previewLayer
    }

    private func metaObjectTypes() -> [AVMetadataObject.ObjectType]
    {
        return [.qr,
                .code128,
                .code39,
                .code39Mod43,
                .code93,
                .ean13,
                .ean8,
                .interleaved2of5,
                .itf14,
                .pdf417,
                .upce
        ]
    }

    public func metadataOutput(_ output: AVCaptureMetadataOutput,
                         didOutput metadataObjects: [AVMetadataObject],
                         from connection: AVCaptureConnection)
    {
        self.requestCaptureSessionStopRunning()
    
        guard let metadataObject = metadataObjects.first,
            let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject,
            let scannedValue = readableObject.stringValue,
            let delegate = self.delegate
    
        else
        {
                return
        }
        
        delegate.scanCompleted(withCode: scannedValue)
    }

    public func requestCaptureSessionStartRunning()
    {
        self.toggleCaptureSessionRunningState()
    }

    public func requestCaptureSessionStopRunning()
    {
        self.toggleCaptureSessionRunningState()
    }

    private func toggleCaptureSessionRunningState()
    {
        guard let captureSession = self.captureSession
    
        else
        {
            return
        }
    
        if !captureSession.isRunning
        {
            captureSession.startRunning()
        }
    
        else
        {
            captureSession.stopRunning()
        }
    }
}

Analysis_ViewController.swift(第二个视图控制器)->

现在,forKey: 已被硬编码为项目 ID 8710908501708,因为我不知道如何将相机扫描的 ID 实际传递到第二个视图控制器中:/

import UIKit

class Analysis_ViewController: UIViewController
{
    @IBOutlet weak var productTitle: UILabel!

    func getData()
    {
        let path = Bundle.main.path(forResource:"ProductCatalog", ofType: "plist")

        let dict:NSDictionary = NSDictionary(contentsOfFile: path!)!
    
        if (dict.object(forKey: "8710908501708" as Any) != nil)
        {
            if let levelDict:[String : Any] = dict.object(forKey: "8710908501708" as Any) as? [String : Any]
            {
                // use a for loop to iterate through all the keys and values in side the "Levels" dictionary
                for (key, value) in levelDict
                {
                    // if we find a key named whatever we care about, we can print out the value
                    if (key == "name")
                    {
                        productTitle.text = (value as! String)
                    }
                }
            }
        }
    }

    // listing the better options that are safer in comparison to the scanned product image
    override func viewDidLoad()
    {
        super.viewDidLoad()

        getData()
    }
}

你的视图控制器中是否有一个变量来保存扫描的 ID?如果没有,您可以将 var itemID: String? 添加到 Scanner_ViewControllerAnalysis_ViewController

然后在你获取扫描代码的函数中,你可以将它设置为变量。

func scanCompleted(withCode code: String) {
    print(code)
    itemID = code // Saves the scanned code to your var
    showAlert_Success(withTitle: (code))
}

为了通过 segue 将数据传递到另一个视图控制器,您可能需要查看 UIViewController 的 segues 方法:documentation here. This answer 也可能有帮助。

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "toAnalysisPage" {
        if let viewController = segue.destination as? Analysis_ViewController {
            viewController.itemID = itemID    
        }
    }
}