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 theviewDidLoad()
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
How to Get the MAC Os X Firewall to Permanently Allow My iOS App
How to Receive Push Notifications of an Other App
Detect Which App Is Currently Running on iOS Using Sysctl
Opens Apple Maps App from iOS App with Directions
Flutter:Not Connecting to iOS Simulator in Android Studio
Best Way to Save and Retrieve Uicolors to Core Data
How to Generate All Possible Combinations
How to Disable Arc for a Single File in Xcode 5
Avcapturevideopreviewlayer Landscape Orientation
Leaving Inputaccessoryview Visible After Keyboard Is Dismissed
How to Use Uiviewcontrolleranimatedtransitioning with Uinavigationcontroller
Scanning Barcode or Qr Code in Swift 3.0 Using Avfoundation
How to Set Status Bar Tint Color on iOS 6
How to Change the App Store's Large Icon on Itunes Connect
Set Delegates to Nil Under Arc
Can't Import Embedded Framework with Xcode 6 Gm
How to Make a Uitableview in Interface Builder Compatible with a 4 Inch Iphone