尝试将变量从一个 class 移动到另一个

Trying to move a variable to from one class to another

我目前正在尝试将一个变量从一个 class 移动到另一个。我正在使用 AVFramework 读取二维码。 QR Code最终读取到一个字符串变量,然后字符串变量读取到一个label.text。我想在另一个 class 的文本视图中使用完全相同的文本。

QRScannerController 包含二维码,而 HistoryView 是我想重新使用变量的地方。问题是,一旦我扫描二维码并移至“历史记录”视图,它什么也看不到。这是我到目前为止所拥有的。下面是 QRScannerController

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){   
    if segue.destination .isKind(of:HistoryView.self){
        let vc2 = segue.destination as! HistoryView
        vc2.previousViewController = self
    }
}

@IBOutlet var messageLabel:UILabel!
@IBOutlet var topbar: UIView!
@IBOutlet var segmentedControl: UISegmentedControl!
//@IBOutlet var textFacts: UITextView!


var captureSession:AVCaptureSession?
var videoPreviewLayer:AVCaptureVideoPreviewLayer?
var qrCodeFrameView:UIView?



let supportedCodeTypes = [AVMetadataObjectTypeUPCECode,
                    AVMetadataObjectTypeCode39Code,
                    AVMetadataObjectTypeCode39Mod43Code,
                    AVMetadataObjectTypeCode93Code,
                    AVMetadataObjectTypeCode128Code,
                    AVMetadataObjectTypeEAN8Code,
                    AVMetadataObjectTypeEAN13Code,
                    AVMetadataObjectTypeAztecCode,
                    AVMetadataObjectTypePDF417Code,
                    AVMetadataObjectTypeQRCode]

@IBAction func unwindToHomeScreen(segue: UIStoryboardSegue) {
    dismiss(animated: true, completion: nil)
}

override func viewDidLoad() {
    super.viewDidLoad()



    // Get an instance of the AVCaptureDevice class to initialize a device object and provide the video as the media type parameter.
    let captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)

    do {
        // Get an instance of the AVCaptureDeviceInput class using the previous device object.
        let input = try AVCaptureDeviceInput(device: captureDevice)

        // Initialize the captureSession object.
        captureSession = AVCaptureSession()

        // Set the input device on the capture session.
        captureSession?.addInput(input)

        // Initialize a AVCaptureMetadataOutput object and set it as the output device to the capture session.
        let captureMetadataOutput = AVCaptureMetadataOutput()
        captureSession?.addOutput(captureMetadataOutput)

        // Set delegate and use the default dispatch queue to execute the call back
        captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        captureMetadataOutput.metadataObjectTypes = supportedCodeTypes

        // Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.
        videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
        videoPreviewLayer?.frame = view.layer.bounds
        view.layer.addSublayer(videoPreviewLayer!)

        // Start video capture.
        captureSession?.startRunning()

        // Move the message label and top bar to the front
        view.bringSubview(toFront: messageLabel)
        view.bringSubview(toFront: topbar)

        // Initialize QR Code Frame to highlight the QR code
        qrCodeFrameView = UIView()

        if let qrCodeFrameView = qrCodeFrameView {
            qrCodeFrameView.layer.borderColor = UIColor.green.cgColor
            qrCodeFrameView.layer.borderWidth = 2
            view.addSubview(qrCodeFrameView)
            view.bringSubview(toFront: qrCodeFrameView)
        }

    } catch {
        // If any error occurs, simply print it out and don't continue any more.
        print(error)
        return
    }

}

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



// MARK: - AVCaptureMetadataOutputObjectsDelegate Methods

public func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {

    // Check if the metadataObjects array is not nil and it contains at least one object.
    if metadataObjects == nil || metadataObjects.count == 0 {
        qrCodeFrameView?.frame = CGRect.zero
        //messageLabel.text = "No QR/barcode is detected"
        return
    }


    // Get the metadata object.
    let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject


    if supportedCodeTypes.contains(metadataObj.type) {
        // If the found metadata is equal to the QR code metadata then update the status label's text and set the bounds
        let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
        qrCodeFrameView?.frame = barCodeObject!.bounds

         if metadataObj.stringValue != nil {
            //captureSession?.stopRunning()

            messageLabel.text = metadataObj.stringValue
            messageLabel.text = messageLabel.text

            //let vc: UINavigationController = storyboard?.instantiateViewController(withIdentifier: "View") as! UINavigationController


            let vc3: UIViewController = storyboard!.instantiateViewController(withIdentifier: "View") //as! UIViewController

            self.present(vc3, animated: true, completion: nil)

        }
    }
}
func transferViewControllerVariables() -> (UILabel){
    return messageLabel
}
}

这是历史视图:

import UIKit
import AVFoundation

class HistoryView: UIViewController, AVCaptureMetadataOutputObjectsDelegate {

    @IBOutlet var textHistory:UITextView!
    var previousViewController: QRScannerController?


    @IBAction func unwindToHomeScreen(segue: UIStoryboardSegue) {
        dismiss(animated: true, completion: nil)
    }

    @IBAction func toMaps(segue: UIStoryboardSegue) {
        let vc3: UIViewController = storyboard!.instantiateViewController(withIdentifier: "front") //as! UIViewController

        self.present(vc3, animated: true, completion: nil)
    }


    override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view.


        let  messageLabel = previousViewController?.transferViewControllerVariables()
        //print(messageLabel.text as Any)
        textHistory.text = messageLabel?.text

        }

        // Do any additional setup after loading the view.


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


}

您应该在 HistoryView 中声明一个 messageLabel。执行segue时,赋值即可。

class HistoryView: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
    var messageLabel: String?

}



class QRCodeScanner: UIViewController {
    func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){   
        if segue.destination.isKind(of:HistoryView.self){
            if let vc2 = segue.destination as? HistoryView {
                vc2.messageLabel = self.messageLabel.text
            }
        }
    }
}

我建议您只将实际文本传递给下一个视图控制器,而不是整个上一个视图控制器。 一般的问题是永远不会调用 prepareForSegue 函数,因为 HistoryView 控制器不是通过 segue 呈现的,而是以编程方式呈现的。

要以编程方式将数据传递给 HistoryView 控制器,请在 QRScannerViewController 的 captureOutput 函数中执行此操作:

let vc3: HistoryView = storyboard!.instantiateViewController(withIdentifier: "View") as! HistoryView
vc3.messagetext = metadataObj.stringValue
self.present(vc3, animated: true, completion: nil)

在历史记录中添加一个新的属性 vc:

class HistoryView: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
    var messageText: String?
}

然后您可以完全删除 prepareForSegue 函数,因为无论如何都不会调用它。