Search code examples
iosswiftdelegatesprotocolsswift5

Protocol Delegate not passing data as expected [Swift5]


I have created simple Protocol Delegate to pass data from One View Controller to Second View Controller - but data seems to be not carried across?

Details: First View Controller have a textField where I type my data (String) to be passed to Second VC. I also have a button with Action to trigger transition to Second View Controller. Second View Controller comes up but data from First View Controller does not show up - expected behaviour was for the Label in Second VC to be updated with my data from First VC. I also have created a segue from Button on FVC to SVC with the identifier 'sendDataIdentifier'.

What I'm doing wrong?

Code and screenshots below:

First View Controller

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!)
    }
}

Second View Controller

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
        }
    }
}

enter image description here


Solution

  • You have it the wrong way around.

    You don't need a delegate pattern in this instance. You need to implement prepare(for segue) in the first view controller and just pass the data to the destination view controller.

    prepare(for segue) isn't called in the destination view controller and the delegate property will be nil in the first view controller because nothing is setting it.

    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
        }
    }