1
votes

I want to shunt the user back to the initial "splash screen" of the app (the first view controller), so that the app can effectively "reset" and operate in offline mode.

Normally I'd use an unwind segue to push the user back to a specific view controller, but an unwind segue (if I understand correctly) needs to be explicitly created from storyboards. I need to effectively do an unwind from any point in the application, and I don't want to be adding unwind segues to all of my dozens of view controllers.

Is there a way to do this programmatically? Can you create an unwind segue on the fly?

My first attempt was to recursively call dismiss on the application's "top" UIViewController. It technically works but it feels like a kludge, doesn't look very good on the screen, and creates a variety of issues regarding the calling of viewDidAppear on each successive view controller that's popped to. Here's the code for it.

extension UIApplication {

    var topController: UIViewController? {
        var topController = keyWindow?.rootViewController
        while topController?.presentedViewController != nil {
            topController = topController?.presentedViewController
        }
        return topController
    }

    // Recursively dismiss until some condition is met
    func dismiss(until: @escaping ((UIViewController?)->Bool), completion: (()->Void)?) {
        var proxy: (()->Void) = { }
        let doDismiss: (()->Void) = {
            if !until(self.topController) {
                DispatchQueue.main.async {
                    self.topController?.dismiss(animated: false, completion: proxy)
                }
            } else {
                completion?()
            }
        }
        proxy = doDismiss
        doDismiss()
    }
}

And it's called like:

UIApplication.shared.dismiss(until: { (topController) -> Bool in
    return topController is SplashScreenViewController
}, completion: nil)

Is there a simpler solution?

1

1 Answers

0
votes

Sorry you can't create any kind of segue in the code itself they have to be setup in the storyboard.

How you achieve what you want and return to the initial view controller depends on how you have setup your controller hierarchy. For example if you are using a UINavigationController and all the view controllers have been pushed onto it then you can just you can just use popToRootViewController(animated: Bool). Anything other than that will depend but you will probably have to handle it manually.

You might need to rethink the structure of your view controller hierarchy.