My app needs to perform some cleanup tasks -delete old data stored locally- every time on startup, before the initial view controller is displayed.
This is because that initial view controller loads the existing data when initialized, and displays it inside a table view.
I set up several breakpoints and found out that the initial view controller's initializer (init?(coder aDecoder: NSCoder)
) is run before application(_:didFinishLaunchingWithOptions)
- even before application(_:**will**FinishLaunchingWithOptions)
, to be precise.
I could place the cleanup code at the very top of the view controller's initializer, but I want to decouple the cleanup logic from any particular screen. That view controller may end up not being the initial view controller one day.
Overriding the app delegate's init()
method and putting my cleanup code there does get the job done, but...
Isn't there a better / more elegant way?
Note: For reference, the execution order of the relevant methods is as follows:
- AppDelegate.init()
- ViewController.init()
- AppDelegate.application(_:willFinishLaunchingWithOptions:)
- AppDelegate.application(_:didFinishLaunchingWithOptions:)
- ViewController.viewDidLoad()
The cleanup task is not lengthy and does not need to run asynchronously: on the contrary, I'd prefer if my initial view controller isn't even instantiated until it completes (I am aware that the system will kill my app if it takes to long to launch. However, it's just deleting some local files, no big deal.).
I am asking this question mainly because, before the days of storyboards, app launch code looked like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
// INITIAL VIEW CONTROLLER GETS INSTANTIATED HERE
// (NOT BEFORE):
MyViewController* controller = [[MyViewController alloc] init];
self.window.rootViewController = controller;
[self.window makeKeyAndVisible];
return YES;
}
...but now, because main storyboard loading happens behind the scenes, the view controller is initialized before any of the app delegate methods run.
I am not looking for a solution that requires to add custom code to my initial view controller.
I am not sure if there is more elegant way but there are definitely some other ways...
I'd prefer if my initial view controller isn't even instantiated until it completes
This is not a problem. All you have to do is to delete a UIMainStoryboardFile
or NSMainNibFile
key from the Info.plist
which tells the UIApplicationMain
what UI should be loaded. Subsequently you run your "cleanup logic" in the AppDelegate
and once you are done you initiate the UI yourself as you already shown in the example.
Alternative solution would be to create a subclass of UIApplicationMain
and run the cleanup in there before the UI is loaded.
Please see App Life Cycle below: