I have two view controllers, One and Two. I go from VC One to VC Two. On VC Two, I select some data that I store in an array. When I press the "Back" button on the navigation bar, I would like to send that array back to VC One.
What's the best way to do this using Swift & Storyboards?
Thanks!
You create the unwind segue as per usual - drag to the exit icon in the scene. Now in the object inspector on the left you will see the unwind segue listed below the view controller, first responder and exit icons. You can click on the unwind segue and give it an identifier in the inspector on the right.
Here is my solution in Swift 3
1) Create a protocol inside the SecondController.swift file. We preferably create the protocol from where we will be getting data from.
protocol Protocol {
func passingDataBack(withString: String)
}
2) Create a variable of type Protocol
var proto: Protocol!
3) Switch to the ViewController.swift file and inherit the Protocol we made from the SecondController.swift file.
class ViewController: UIViewController, Protocol {
}
4) We then want to conform to the Protocol we made by creating the function we made
func passingDataBack(withString: String) {
// withString will return the value that has been passed from our SecondController class
self.title = withString
}
5) Use the prepareForSegue method and segue to the SecondController class
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as? SecondController
vc?.proto = self //This line will instantiate the protocol to our ViewController class
}
6) Go back to our SecondController.swift file and use the didSelectRow method and pass our data
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
proto.passingDataBack(withString: items[indexPath.row]) //Call the protocol and the function then pass our data.
_ = self.navigationController?.popViewController(animated: true) //This will pop back to our previous controller.
}
* Important Things To Remember!!! *
You must set the protocol from controllerB to instantiate to controllerA when switching from controllerA to controllerB
In our example, we moved from ViewController to SecondController. We instantiate our protocol from our SecondController by doing
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as? SecondController
vc?.proto = self //This line will instantiate the protocol to our ViewController class
}
If you do not do this, you will get a Thread 001 error on this line
proto.passingDataBack(withString: items[indexPath.row]) //Call the protocol and the function then pass our data.
Source code Github
If you were presenting a modal view with Done and Cancel buttons (sort of like a picker), grabbing the value during an unwind segue method would probably be the easiest.
Given that you want to use the navigation controller's native Back button, the best practice would probably be to implement a protocol that VC One can conform to, and then update VC One as soon as the data on VC Two is selected. Something like:
In VCTwo.swift:
protocol VCTwoDelegate {
func updateData(data: String)
}
class VCTwo : UIViewController {
var delegate: VCTwoDelegate?
...
@IBAction func choiceMade(sender: AnyObject) {
// do the things
self.delegate?.updateData(self.data)
}
...
}
and in VCOne.swift:
class VCOne: ViewController {
...
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "VCTwoSegue" {
(segue.destinationViewController as VCTwo).delegate = self
}
}
...
}
extension VCOne: VCTwoDelegate {
func updateData(data: String) {
self.internalData = data
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With