1
votes

I have seen too much threads on how to go back to previous View controller, that makes sens and are easy also to implement. But in my case there is only one type of complication. Consider the following situation.

  • VC1 --Opens--> VC2: vc2 is a viewcontroller that is showing a Form. On correct filling the user is taken to another VC. call it vC3
  • VC2 --Opens--> VC3: vc3 is a view controller that takes swipe card information and if the information provided is correct it takes to VC4

  • VC3 --Opens--> VC4:.

VC4 is the viewcontroller that loads up all user contacts and send information/data to that selected contact. SO far it is fine. now there is 2 conditions, if the data that I send is correctly sent then I have to go back to VC1 directly, and if the data is not sent then I have to go back to vc2 directly to take up information again.

so what are the best thing to handle this situation. Please suggest.

UPDATE:

I am using Tab bar controller, in that controller under one of that View , I am opening other VIew controller from this in series. Like from this Opening VC2 that opens VC3 and so on...

This is how I am showing my ViewController 2

let myVC2 = self.storyboard?.instantiateViewController(withIdentifier: "idMyVC2") as MyVC2 
myVC2.modalPresentationStyle = .fullScreen 
self.present(myVC2,animated : true) 
4
Are you working with storyboard segues, or do you want to do this via direct UINavigationController pop...? - Andreas Oetjen
How are you presenting the VC2 from VC1, VC3 from VC2 and so on? - Kamran
read updated question now - A.s.ALI
yes............. - A.s.ALI
Just chain delegates between all of the view controllers that you are presenting and use them to dismiss the specific view controller on top of the one that you want to go back to. If A presents B, B presents C, C presents D, and D presents E, if you go through the delegate and dismiss B (from E), it will automatically dismiss C, D, and E together and take the user back to A. - fake girlfriends

4 Answers

1
votes

Plug this into a playground and mess around with it:

import UIKit

protocol DismissDelegate: AnyObject {
    func dismissVC(_ presenting: Int)
}

class VC1: UIViewController, DismissDelegate {
    func dismissVC(_ presenting: Int) {
        guard presenting == 1 else {
            return
        }
        print("dismiss 2, 3, 4, 5")
    }
}
class VC2: UIViewController, DismissDelegate {
    weak var vc2Delegate: DismissDelegate?
    func dismissVC(_ presenting: Int) {
        guard presenting == 2 else {
            return vc2Delegate!.dismissVC(presenting)
        }
        print("dismiss 3, 4, 5")
    }
}
class VC3: UIViewController, DismissDelegate {
    weak var vc3Delegate: DismissDelegate?
    func dismissVC(_ presenting: Int) {
        guard presenting == 3 else {
            return vc3Delegate!.dismissVC(presenting)
        }
        print("dismiss 4, 5")
    }
}
class VC4: UIViewController, DismissDelegate {
    weak var vc4Delegate: DismissDelegate?
    func dismissVC(_ presenting: Int) {
        guard presenting == 4 else {
            return vc4Delegate!.dismissVC(presenting)
        }
        print("dismiss 5")
    }
}
class VC5: UIViewController {
    weak var vc5Delegate: DismissDelegate?
    func dismissStack(at presenting: Int) {
        vc5Delegate?.dismissVC(presenting)
    }
}

let vc1 = VC1()

let vc2 = VC2()
vc2.vc2Delegate = vc1

let vc3 = VC3()
vc3.vc3Delegate = vc2

let vc4 = VC4()
vc4.vc4Delegate = vc3

let vc5 = VC5()
vc5.vc5Delegate = vc4

vc5.dismissStack(at: 1) // prints: dismiss 2, 3, 4, 5
vc5.dimissStack(at: 2) // prints: dismiss 3, 4, 5

The setup is very basic, each view controller is chained through a delegate. Because there is more than one view controller, we created a protocol. That protocol is just a method that takes an integer argument which is the view controller that should perform the dismiss (the presenting view controller). Then when you want to perform a dismiss, call the delegate (doesn't have to be from the 5th view controller), specify the presenting view controller, and the delegate will go down the chain and check if it's the presenting view controller (if it is, it will dismiss everything above it) or not (if it isn't, it will step down one view controller and repeat the process).

VC5 has a method called dismissStack(at:) which lets you put in an integer of the view controller you want to dismiss at. Therefore, if you dismiss at 2, then view controllers 3, 4, 5 will be dismissed. You can, obviously, place this method into the other view controllers as well.

0
votes

You can do in various way, one them is like below:-

Hierarchy of view controllers be like :-

NavigationController -> VC1 -> VC2 -> VC3 -> VC4(using push).Now use below code to change your controller

If pop to root use :-

for controller in self.navigationController!.viewControllers as Array {
    if controller.isKind(of: VC1) {
        self.navigationController!.popToViewController(controller, animated:    true)
        break
    }
}

if for pop go to at VC3 simply pop to root.

I hope it will help you,

Thanks

0
votes

way that i used most is

for controller in self.navigationController.controllers {
      if let desiredVC = controller as? DesiredViewControllerName {
          self.navigationController!.popToViewController(desiredVC, animated: true)
      }
}
0
votes

Here is a way i used

for controller in self.navigationController!.viewControllers 
{
    if let vc = controller as? LoginViewController 
    {
        self.navigationController!.popToViewController(vc, animated:    true)
              break
    }
}