协议委托未按预期传递数据 [Swift5]

Protocol Delegate not passing data as expected [Swift5]

我创建了简单的协议委托来将数据从一个视图控制器传递到第二个视图控制器 - 但数据似乎没有被传送?

详情: 第一个视图控制器有一个文本字段,我在其中键入要传递给第二个 VC 的数据(字符串)。 我还有一个带有 Action 的按钮,用于触发到 Second View Controller 的转换。 第二个视图控制器出现,但来自第一个视图控制器的数据未显示 - 预期的行为是第二​​个 VC 中的标签将使用第一个 VC 中的数据进行更新。 我还创建了一个从 FVC 上的 Button 到 SVC 的 segue,标识符为 'sendDataIdentifier'.

我做错了什么?

下面的代码和截图:

第一个视图控制器

import UIKit

protocol SendDataDelegte {
    func sendData(data: String)
}

class FirstViewController: UIViewController {

    var delegate: SendDataDelegte? = nil

    @IBOutlet weak var dataCaptured: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func sendDataButton(_ sender: Any) {
        let dataToBeSent = self.dataCaptured.text
        self.delegate?.sendData(data: dataToBeSent!)
    }
}

第二个视图控制器

import UIKit

class SecondViewController: UIViewController, SendDataDelegte {

    @IBOutlet weak var dataRetrived: UILabel!
    @IBAction func closeButton(_ sender: Any) {
         dismiss(animated: true, completion: nil)
    }

    func sendData(data: String) {
        self.dataRetrived.text = data
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "sendDataIdentifier" {
            let firstVC: FirstViewController = segue.destination as! FirstViewController
            firstVC.delegate = self
        }
    }
}

你想错了。

在此实例中您不需要委托模式。您需要在第一个视图控制器中实现 prepare(for segue) 并将数据传递给目标视图控制器。

prepare(for segue) 未在目标视图控制器中调用,delegate 属性 在第一个视图控制器中将是 nil,因为没有设置它。

class FirstViewController: UIViewController {

    @IBOutlet weak var dataCaptured: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let dest = segue.destination as? SecondViewController {
            dest.text = self.dataCaptured.text
        }
    }
}

class SecondViewController: UIViewController {

    @IBOutlet weak var dataRetrived: UILabel!
    var text: String?
    @IBAction func closeButton(_ sender: Any) {
         dismiss(animated: true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewWillAppear(_ animated:Bool) {
        super.viewWillAppear(animated)
        self.dataRetrieved.text = text
    }
}

要向前推送数据,可以使用present方法

并使用委托向后发送数据。

示例:

第一个屏幕

import UIKit

protocol SendDataDelegte: class {
    func sendData(data: String)
}


class FirstViewController: UIViewController, SendDataDelegte {
    
    var dataCaptured: UITextField = {
        let txt = UITextField()
        txt.translatesAutoresizingMaskIntoConstraints = false
        txt.backgroundColor = .lightGray
        return txt
    }()
    
    var sendDataButton: UIButton = {
        let btn = UIButton()
        btn.translatesAutoresizingMaskIntoConstraints = false
        btn.backgroundColor = .lightGray
        return btn
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupUI()
    }

    @objc func sendDataButtonAction() {
        let dataToBeSent = self.dataCaptured.text
        let vc = SecondViewController()
        vc.delegate = self
        vc.getDataLabel.text = dataToBeSent
        vc.modalPresentationStyle = .popover
        present(vc, animated: true, completion: nil)
    }
    
    func sendData(data: String) {
        sendDataButton.setTitle(data, for: .normal)
    }
    
    func setupUI() {
        view.backgroundColor = .blue
        view.addSubview(dataCaptured)
        dataCaptured.widthAnchor.constraint(equalToConstant: 200).isActive = true
        dataCaptured.heightAnchor.constraint(equalToConstant: 100).isActive = true
        dataCaptured.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        dataCaptured.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        
        view.addSubview(sendDataButton)
        sendDataButton.setTitle("Send Data", for: .normal)
        sendDataButton.titleColor(for: .normal)
        sendDataButton.widthAnchor.constraint(equalToConstant: 200).isActive = true
        sendDataButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
        sendDataButton.topAnchor.constraint(equalTo: dataCaptured.bottomAnchor, constant: 50).isActive = true
        sendDataButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        
        sendDataButton.addTarget(self, action: #selector(sendDataButtonAction), for: .touchUpInside)
    }
}

第二屏

import UIKit

class SecondViewController: UIViewController {
    
    weak var delegate: SendDataDelegte?
    
    var getDataLabel: UILabel = {
        let lbl = UILabel()
        lbl.translatesAutoresizingMaskIntoConstraints = false
        return lbl
    }()

    var dataCaptured: UITextField = {
        let txt = UITextField()
        txt.translatesAutoresizingMaskIntoConstraints = false
        txt.backgroundColor = .lightGray
        return txt
    }()
    
    var sendDataButton: UIButton = {
        let btn = UIButton()
        btn.translatesAutoresizingMaskIntoConstraints = false
        btn.backgroundColor = .lightGray
        return btn
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupUI()
    }
    
    @objc func sendDataButtonAction() {
        let string = dataCaptured.text!
        delegate?.sendData(data: string)
        dismiss(animated: true, completion: nil)
    }
    
    func setupUI() {
        view.backgroundColor = .yellow
    
        view.addSubview(getDataLabel)
        getDataLabel.backgroundColor = .lightGray
        getDataLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
        getDataLabel.heightAnchor.constraint(equalToConstant: 50).isActive = true
        getDataLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
        getDataLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
 
        view.addSubview(dataCaptured)
        dataCaptured.widthAnchor.constraint(equalToConstant: 200).isActive = true
        dataCaptured.heightAnchor.constraint(equalToConstant: 100).isActive = true
        dataCaptured.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        dataCaptured.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        
        view.addSubview(sendDataButton)
        sendDataButton.setTitle("Send Data", for: .normal)
        sendDataButton.titleColor(for: .normal)
        sendDataButton.widthAnchor.constraint(equalToConstant: 100).isActive = true
        sendDataButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
        sendDataButton.topAnchor.constraint(equalTo: dataCaptured.bottomAnchor, constant: 50).isActive = true
        sendDataButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        
        sendDataButton.addTarget(self, action: #selector(sendDataButtonAction), for: .touchUpInside)
    }
    

}

当我们在第一个屏幕上调用 present 方法时,我们将数据发送到第二个屏幕的标签并将委托分配给自己。

当我们点击第二个屏幕上的按钮时,我们调用委托方法并将文本发送到第一个屏幕上的按钮标题。