You should define a (public) method in your application delegate class and call it when necessary. In that method, you should re-instantiate your initial view controller and set it as root view controller of your UIWindow instance (you should have an ivar with it).
AppDelegate.h:
- (void) resetApp;
AppDelegate.m:
- (void) resetApp {
TopViewController* controller = [[TopViewController alloc] init];
_window.rootViewController = controller;
}
Edit: If you are usign storyboards, this code works:
AppDelegate.swift (because it's 2017):
func resetApp() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
guard let newRoot = storyboard.instantiateInitialViewController() else {
return // This shouldn't happen
}
self.window?.rootViewController = newRoot
}
(This assumes your app's initial storyboard -the one specified in Info.plist- is called "Main.storyboard")
If your app is designed in such a way that long or asynchronous operations might be in progress when this reset happens, additional considerations should be taken to deal with them. For starters, all view controllers that aren't implemented as singletons or retained by such long-lived objects will likely be deallocated.