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?