Passing Data Between 2 Uiviewcontroller Using Delegate and Protocol

Passing data between 2 UIViewController using delegate and protocol

Not quite right. First you need to assign the delegate property in the first view controller so the second view controller knows which object to send messages to.

FirstViewController.m

controller.delegate = self;

Second, you have the sending and receiving of your delegate method backwards. You have it setup in a way where the FirstViewController is expected to call sendDataBackToFirstController on the second controller. In a delegate pattern, the SecondViewController is the one that sends the message and optionally sends data with that method. So, you should change your delegate declaration to something like this:

@protocol sampleDelegate <NSObject>
- (void)secondControllerFinishedWithItems:(NSArray* )newData;
@end

Then, when your SecondViewController finishes its tasks and needs to notify its delegate, it should do something like this:

// ... do a bunch of tasks ...
// notify delegate
if ([self.delegate respondsToSelector:@selector(secondControllerFinishedWithItems:)]) {
[self.delegate secondControllerFinishedWithItems:arrayOfNewData];
}

I added an extra if statement here to check to make sure the delegate will respond to the method we want to send it before actually sending it. If we had optional methods in our protocol and did not have this, the app would crash.

Hope this helps!

Delegate/Protocols Passing data from one view controller to another

The most obvious problem lies here:

if let push = self.storyboard?.instantiateViewController(withIdentifier: "MainScreenVC") as? MainScreenVC {
push.transferCurrencyDelegate = self
}

You have to realize that instantiateViewController creates a new view controller - it's not the reference to the view controller presented at the screen. In that code you just created a completely new view controller and then set its delegate to self, but otherwise nothing else.

Without knowing the context it is really hard to suggest anything - prepare(for:) segue might be the place where you want to set the delegate. Anyway, the problem is that you have to obtain a reference to the controller that is presented on the screen, the one that is supposed to be reacting to those events.

Moreover, from the memory management aspect, you should really consider making the delegate property a weak one to prevent memory leaks.

EDIT

So after seeing the minimal working example you provided at link, I think I can provide the solution on how to get that string to the SecondVC.

Your first view controller with comments:

import UIKit

class ViewController: UIViewController {

var newLine: String = "EUR"

@IBAction func push(_ sender: Any) {
// here the secondVC does not exist yet, calling delegate.transferWord() here would have no sense
// performSegue will create that secondVC, but now it does not exist, nor it is set up as the delegate
self.performSegue(withIdentifier: "ViewController", sender: navigationController)
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let secondVC = segue.destination as? SecondVC, segue.identifier == "ViewController" {
// at this moment secondVC did not load its view yet, trying to access it would cause crash
// because transferWord tries to set label.text directly, we need to make sure that label
// is already set (for experiment you can try comment out next line)
secondVC.loadViewIfNeeded()
// but here secondVC exist, so lets call transferWord on it
secondVC.transferWord(word: newLine)
}
}
}

No need for delegates here, because your ViewController is the one pushing the SecondVC to the Navigation controller - that means that you can access it directly in prepare(for:), as you can see above.

Now the SecondVC is super simple (I omitted unnecessary code):

import UIKit

class SecondVC: UIViewController {

@IBOutlet weak var label: UILabel!

func transferWord(word: String) {
label.text = word
}
}

Storyboards can stay as they are.

How to pass data between UIViewControllers with protocols/delegates

Objects don't exactly listen for method calls. They sit there, waiting to invoked.

The line

self.delegate?.messageData(inputMessage.text!)

From your SenderViewController is a function call. (The term method and function are pretty much interchangeable, although the method is usually used for the functions of objects.) It invokes the function messageData in ViewController.

passing data delegates and protocols swift

According to your code, your delegate field is not set. ! will force the unwrap of the optional delegate field. Your have to set your delegate before call it.

Simply assign a value to it, or use optional chaining.

For example, you could:

  • set a value to delegate in the viewDidLoad() method, for example
override func viewDidLoad() {
super.viewDidLoad()
// HERE
self.delegate = ArtistViewController()
getItunesData()

tableView.dataSource = self
tableView.delegate = self
tableView.register(UINib(nibName: "artistCell", bundle: nil), forCellReuseIdentifier: "artistCell")
}
  • call the delegate only if it's set with delegate?.loadArtistViewModel(_:).

You may replace var delegate: artistViewModelDelegate! by var delegate: artistViewModelDelegate? to prevent this type of errors.



Related Topics



Leave a reply



Submit