0
votes

My app has a navigation controller where the first view controller is a login screen and all other screens are pushed on top.

I would like to unwind to the login screen whenever any http request to the backend returns a 401 error.

What I had in mind was to add an extension to the ViewController class with something like this:

extension UIViewController {
    func unwindToLoginScreen() {
        performSegue(withIdentifier: loginScreen)
    }
}

And the segue would be an unwind segue. Then, whenever the request fails I call the view controller's unwindToLoginScreen method.

However, the problem with this approach is that I would have to remember to create said unwind segues on the storyboard for all new view controllers that I added to the project.

So far I think the ideal plan would be to be able to create the unwind segue programatically instead of using the storyboard. So, my unwindToLoginScreen() extension method would work in any new view controller by default. Something like:

extension UIViewController {
    func unwindToLoginScreen() {
        let segue = UnwindSegue(identifier: "blablah", segue: LoginViewController.unwindToLoginViewController)
        segue.perform()
    }
}

Is it possible to do something like this?

1
It is possible, I've done so in the past. I don't recall how :POscar Apeland

1 Answers

5
votes

You can't create segues in code, but you can pop to the root of the UINavigationController's stack:

func returnToLoginScreen() {
    self.navigationController?.popToRootViewController(animated: true)
}

If you want to pop to a viewController that isn't the root, you can find it in the array of viewController's managed by the UINavigationController and then call popToViewController:

// pop to second viewController in the stack
self.navigationController?.popToViewController(self.navigationController!.viewControllers[1], animated: true)

... or search for the ViewController by type:

if let loginVC = self.navigationController?.viewControllers.first(where: { $0 is LoginViewController }) {
    self.navigationController?.popToViewController(loginVC, animated: true)
}