如何将扫描的条形码ID从第一个View Controller传递到第二个View Controller的UILabel?

问题描述

这是我在程序中使用的条形码扫描教程,因此,当您阅读我的代码时,您会拥有更多的上下文:Link

这是我的程序到目前为止执行的操作:本质上,当我用手机扫描物品的条形码时,UIAlert会弹出并显示显示的条形码ID和一个按钮,提示用户打开“结果”页面。一切都很好,但是如何将相同的扫描条形码ID传递到结果页面上的标签?我已经坚持了两天,即使这看起来很容易。

非常感谢任何帮助

这是我的相关代码

ProductCatalog.plist -> Link to Image

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

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,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实际传递到第二个View Controller中:/

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将数据传递到另一个视图控制器,您可能需要研究以下针对segue的UIViewController方法:documentation here。这个answer也可能有帮助。

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