How to Init Again in Controller Swift
Then now you accept gear up upwardly unlike view controllers in the storyboard and wanting to pass the input data gotten from 1 view controller to another for brandish purpose or processing. This post will bear witness yous three means to do it and discuss when to use them.
The 3 ways are :
- Segue, in prepareForSegue method (Frontward)
- Delegate (Backward)
- Setting variable direct (Forrard)
When to utilise them
ane - Segue, in prepareForSegue method
Assume you accept two view controller fix up in storyboard like this,
Link the InputViewController to DisplayViewController by clicking the yellow round icon on pinnacle of InputViewController, then press and agree control and elevate it to DisplayViewController. After releasing the mouse click, select 'Show' inside Transmission Segue.
Then select the segue between view controller, and set an identifier for information technology, we will employ this identifier on the side by side step. Usually my naming convention will be "sourceVCtoDestinationVC".
When the Side by side push button is tapped, we will tell the InputViewController to perform the segue. The segue identifier is used hither. This method tells the InputViewController to perform a segue to DisplayViewController.
The sender parameter refer to the object which initiated this segue, nosotros put 'self' to signal that this segue is initiated by the InputViewController.
class InputViewController: UIViewController { ... @IBAction func nextTapped(_ sender: Whatever) { self.performSegue(withIdentifier: "InputVCToDisplayVC", sender: cocky) } ... }
You can now build the app and tap Side by side, it will show the display view controller, but the data is not passed notwithstanding.
In InputViewController, if there is a MARK: - Navigation
, uncomment the code beneath information technology. Else add the post-obit code :
override func prepare(for segue: UIStoryboardSegue, sender: Whatsoever?) { }
The prepare(for segue:, sender:) method volition be called past the view controller just earlier a segue is performed. You can laissez passer the information to the next view controller here.
Lets put a name
cord variable in Display View Controller to hold the proper name input data.
class DisplayViewController: UIViewController { ... var name: Cord? ... }
In the prepareForSegue
method in InputViewController, add together the following code :
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if(segue.identifier == "InputVCToDisplayVC"){ permit displayVC = segue.destination as! DisplayViewController displayVC.name = nameTextField.text } }
This volition ready the name variable of the DisplayViewController before it is displayed. Since we already know the destination of the segue (the view controller to be presented) is a DisplayViewController, we can safely downcast it to DisplayViewController.
Within the DisplayViewController viewDidLoad method, y'all can set nameLabel.text = name
. At present y'all have successfully pass information forward from i controller to another using prepareForSegue
method.
2 - Delegate
So now you want to pass a data to the previous view controller (InputViewController) as the current view controller (DisplayViewController) volition be dismissed/popped. How practise we do this equally segue is uni directional? Assume the view controller is presented using the segue mode shown above , we will add together a protocol and a weak variable named 'delegate' to the destination (DisplayViewController) view controller.
// DisplayViewController.swift protocol DisplayViewControllerDelegate : NSObjectProtocol{ func doSomethingWith(data: String) } class DisplayViewController: UIViewController { weak var delegate : DisplayViewControllerDelegate? }
This is the Delegate Concept and Protocol used by Apple Cocoa Library. This is how the tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
work when you tap on a row in tabular array view. The reason for using weak var for the consul is to avoid retain bicycle (both source view controller and destination view controller has a strong reference to each other, causing ARC to not free the retentivity), read more about ARC memory direction here .
The gist of it is that you don't need to know what class is the source controller, as long as the source controller implements the method doSomethingWith(data:), it will work. At that place might be cases where multiple controller has their own segue to the same destination view controller, it will be cumbersome to recollect what class is the source view controller, and then we volition just brand sure all of the source view controllers arrange to the DisplayViewControllerDelegate protocol past implementing the doSomethingWith(data:) method.
In the prepareForSegue method of the source view controller, set the delegate variable to self.
// InputViewController.swift override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if(segue.identifier == "InputVCToDisplayVC"){ let displayVC = segue.destination as! DisplayViewController displayVC.delegate = self } }
Yous might meet Xcode complain that Cannot assign value of type 'InputViewController' to type 'DisplayViewControllerDelegate?'
, this is because you didn't adapt the view controller to DisplayViewControllerDelegate, you tin ready information technology by adding it to the back end view controller announcement line :
class InputViewController: UIViewController, DisplayViewControllerDelegate { ... }
Shortly subsequently, you lot will come across Xcode complains Type 'InputViewController' does not conform to protocol 'DisplayViewControllerDelegate'
, this is because you haven't implement the doSomethingWith(data:) declared in the DisplayViewControllerDelegate protocol. Just add together the method to the view controller to fix information technology :
// InputViewController.swift func doSomethingWith(data: String) { // Do something hither later receiving data from destination view controller }
So now when you want to laissez passer a data from destination view controller back to the source view controller, y'all can call the delegate like this :
// DisplayViewController.swift // Whenever you want to pass a data back if let delegate = delegate{ delegate.doSomethingWith(data: "John Cena") }
And then the doSomethingWith(information:) method on the source view controller will exist called.
3 - Setting variable straight
This pace is for presenting view controller or pushing view controller programmatically without using storyboard segue.
In some cases, a view controller might have multiple entry point from other view controllers, which is non post-obit a specified menses. You can use Storyboard ID to initialize the destination view controller programmatically. Select the view controller in storyboard, and set the "Storyboard ID" in the Identity Inspector tab.
So in the source view controller, you can present information technology similar this :
// InputViewController.swift @IBAction func nextTapped(_ sender: Any) { // the name for UIStoryboard is the file proper noun of the storyboard without the .storyboard extension let displayVC : DisplayViewController = UIStoryboard(proper name: "Master", package: nil).instantiateViewController(withIdentifier: "DisplayVC") every bit! DisplayViewController displayVC.name = "John Cena" self.nowadays(displayVC, blithe: true, completion: nil) }
If you are using xib, refer to this Stack Overflow reply.
When to use which method for passing data
For forward data passing
If you are using segue to go to next view controller, use the prepareForSegue. The pros of this method is that this is straight frontward and easy, the cons is that this method is only effective for uncomplicated segue menstruum.
If you are using view controller with Xib, without segue menstruum, or programmatically, instantiate the view controller programmatically and set up variable directly (Forrard).
For backward data passing
Use the consul pattern.
Notes
Avoid using NSNotification to pass information equally this will make your life hard when debugging later (you need to bank check which view controllers has the observer for a sure NSNotification Name).
Source: https://fluffy.es/3-ways-to-pass-data-between-view-controllers/
0 Response to "How to Init Again in Controller Swift"
Post a Comment