iosswiftswift-protocolsswift-class

How to send data with Protocols and Delegate with IBAction (Button click)


Hello I went across protocols and delegates in course recently (iOS dev guy in production here).

I tried to apply this at my simple app, which basically do nothing, but I wanted to pass data from one VC to another.

More specifically: ViewControllerOne has button and set segue for going to my ViewControllerTwo, ViewControllerTWo has also button which with I want now only to print some text when I click on button on ViewControllerTwo.

Here is the code:

Receiver

    class ViewControllerOne: UIViewController, DataDelegate {
      var vcTwo = ViewControllerTwo()        

      override func viewDidLoad() {
       super.viewDidLoad()
    
      vcTwo.delegate = self
      }
    
      func printThisNumber(type: Int){
        print("This is a test of delegate with number: \(type)")
      }
    

Sender with protocol defined

protocol DataDelegate {
  func printThisNumber(type: Int)
}

class ViewControllerTwo: UIViewController {

  var delegate: DataDelegate?

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



  @IBAction func myButtonPressed(_ sender: UIButton) {
     delegate?.printThisNumber(type: 1)

  }
}

It sends nothing and I tried to troubleshoot it with print statement shows nil, obviously (when button clicked), but even if I print delegate in viewDidLoad, it shows nil.

When I tried another approaches from StackOverflow, like declaring delegate as weak var, Xcode does not even allow me to do so.

Thanks anybody who will spend his/her time on this issue and would propose anything what would help me to understand it or resolve.

If that will be sorted out, my future intention is to get some data on VCTwo and update with that data e.g. Label text on VCOne.

Thank you Best Regards Petr


Solution

  • Since you are using segue for navigating to ViewControllerTwo, the vcTwo instance in ViewControllerOne will not be the pushed view controller instance. You will have to override prepare(for segue in ViewControllerOne to access that instance of ViewControllerTwo, and then set the delegate.

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let vcTwo = segue.destination as? ViewControllerTwo {
            vcTwo.delegate = self
        }
    }