Search code examples
swiftsegueviewcontrollerunwind-segueremovefromsuperview

Segueing from Child ViewController


I have a situation where I am presenting a child view controller "B" onto another view controller "A". View controller "B" has 5 buttons which segue(push) to a third view controller, "C". The problem is once I'm at view controller "C", I want to be able to use an unwind segue to go from C-->A without B showing up in the middle.

    // view controller A class

    class AViewController: UIViewController {        

            @IBAction func goToViewControllerB(_ sender: UIButton) {
                   let viewControllerB = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "viewControllerB_ID") as! BViewController
                   self.addChild(viewControllerB)
                   viewControllerB.view.frame = self.view.frame
                   self.view.addSubview(viewControllerB.view)
                   viewControllerB.didMove(toParent: self)
           }

           @IBAction func unwindToStart(segue: UIStoryboardSegue) {
                  print("back from view controller C!")
           }

   }

   //view controller B class

   class BViewController: UIViewController {

           override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
                  if let identifier = segue.identifier {
                        switch identifier {
                              case "segueFromBToC_1":
                                    if let destVC = segue.destination as? CViewController {
                                        //pass data
                                    }
                              // ... cases 2-4
                              case "segueFromBToC_5":
                                    if let destVC = segue.destination as? CViewController {
                                        //pass data
                                    }
                              default: break
                         }                   
                  }
          }

    }

    // empty CViewController class

I know that putting the following code in my view controller B class will remove it from the parent view controller, "A", but then I can't segue from "B" to "C" anymore as "B" doesn't exist.

   self.view.removeFromSuperview()
   self.removeFromParent()
   self.willMove(toParent: nil)

I was wondering where I should put the above code or if I should segue from a child view controller at all? I also haven't used navigation controllers as I don't know how to implement them with a child view controller. Should I have @IBAction outlets for each of the 5 buttons and put the above code in there?


Solution

  • UPDATE: I was able to fix it by detaching the 5 push segues from the buttons and have each of the 5 push segues go directly from view controller B to view controller C The 5 segues from view controller B to view controller C. I then had an @IBAction for each button where I had the following code in view controller B:

    class BViewController: UIViewController {
    
           @IBAction func button1ToVC3(_ sender: UIButton) {
              segueAndRemoveSelf(segueName: "segueFromBToC_1")
          }
    
          @IBAction func button2ToVC3(_ sender: UIButton) {
             segueAndRemoveSelf(segueName: "segueFromBToC_2")
          }
    
          @IBAction func button3ToVC3(_ sender: UIButton) {
             segueAndRemoveSelf(segueName: "segueFromBToC_3")
          }
    
          @IBAction func button4ToVC3(_ sender: UIButton) {
             segueAndRemoveSelf(segueName: "segueFromBToC_4")
          }
    
          @IBAction func button5ToVC3(_ sender: UIButton) {
             segueAndRemoveSelf(segueName: "segueFromBToC_5")
          }
    
           override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
                  if let identifier = segue.identifier {
                        switch identifier {
                              case "segueFromBToC_1":
                                    if let destVC = segue.destination as? CViewController {
                                        //pass data
                                    }
                              // ... cases 2-4
                              case "segueFromBToC_5":
                                    if let destVC = segue.destination as? CViewController {
                                        //pass data
                                    }
                              default: break
                         }                   
                  }
          }
    
    }
    
    extension BViewController {
        func segueAndRemoveSelf(segueName: String) {
            self.performSegue(withIdentifier: segueName, sender: self)
            self.view.removeFromSuperview()
            self.removeFromParent()
            self.willMove(toParent: nil)
        }
    }
    

    Not sure if this is best practice though.