I'm trying to get a destination View Controller to push a new View Controller, but I can't seem to get it, programmatically or via storyboard segues.
Here's what I'm trying to do:
I have 3 View Controllers (let's call them A, B, and C). All three were created (designed?) in the storyboard. I start on view controller A, and when the user presses a button, I want to present view controller B modally, and then when the user selects a cell in view controller B, I want view controller B to be dismissed (modally), and I want view controller A to push a a new view controller (view controller C).
The way I've tried to implement this thus far is when the user presses the button in view controller A, I programmatically modally push view controller B, and then when the user selects a cell in view controller B, I segue back to view controller A, and try to push view controller C from view controller B's prepareForSegue function like this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let viewA = segue.destinationViewController as? ViewControllerA {
let cell = sender as! ViewControllerBTableViewCell
var viewC = storyboard?.instantiateViewControllerWithIdentifier("viewControllerC") as! ViewControllerC
viewC.IDToDisplay = cell.userID
viewA.navigationController?.pushViewController(viewC, animated: true)
self.dismissViewControllerAnimated(true, completion: nil)
}
}
However, when I run this... view controller C is never pushed!
The reason I need to push view controller C from view controller A is that I need the user to be able to navigate back to view controller A from view controller C using the "back" button... not back to view controller B from view controller C.
Essentially the flow I am trying create is view A -> view B modally -> view C ---> back to view A as if view B disappeared (because it should). Please note, however, that view B does need to be able to set the IDToDisplay
value of view C before view A pushes to view C.
Is there a clean (standard) way to implement this? Or am I going to have to get janky?
You can solve this problem in two ways
first option: you can create one clousure var in your B controller and execute it before you dissmiss the B controller
for example: In BController
class BTableViewController: UITableViewController {
var pushClosure:(()->())?
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
pushClosure?()
self.navigationController?.dismissViewControllerAnimated(true, completion: nil)
}
}
And in A controller in the prepareForSegue do something like that
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "SegueID" {
let nextView:BController = segue.destinationViewController as! BController
nextView.pushClosure = {
self.performSegueWithIdentifier("SegueID To C Controller", sender:nil)
}
}
}
The second Option is to implement your own delegate in the BController
protocol ClassNameDelegate{
func pushToC()
}
class ClassName: NSObject {
var delegate:ClassNameDelegate?
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.delegate.pushToC()
self.navigationController?.dismissViewControllerAnimated(true, completion: nil)
}
}
And in A controller
class AViewController:ClassNameDelegate{
func pushToC(){
self.performSegueWithIdentifier("SegueID To C Controller", sender:nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "SegueID" {
let bController:BController = segue.destinationController as! BController
bController.setDelegate = self
}
}
}
I hope it helps you.