Search code examples
iosiphoneswiftuiviewcontrolleruistoryboardsegue

Push new View Controller from destination View Controller (swift)


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?


Solution

  • 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.