The following works for me, if I use a UISplitViewController
-based structure (tested on iOS 8+):
Remove Storyboard from Projects General -> Deployment Info, so the dropdown looks like the below and you have to configure the storyboard in code.

Somewhere in AppDelegate.m
- (void)setupViewControllers
{
// check for thread, as this method might be called by other (e.g. logout) logic
if ([NSThread currentThread] != [NSThread mainThread]) {
dispatch_async(dispatch_get_main_queue(), ^{
[self setupViewControllers];
});
return;
}
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
UIViewController *vc =[storyboard instantiateInitialViewController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = vc;
// configure split vc
// Note: I reference split vc for my own purpose, but it is your mater of choice
self.splitViewController = (UISplitViewController *)self.window.rootViewController;
self.splitViewController.delegate = self;
self.splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible;
self.splitViewController.preferredPrimaryColumnWidthFraction = 0.5;
[self.window makeKeyAndVisible];
}
To avoid code duplicates, call this function from application:didFinishLaunchingWithOptions:
as a first-time setup
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// some code...
[self setupViewControllers];
// Optional: add splash view (e.g. [self addSplashView];)
// some code...
}
Inside a view controller you are ready to present UI to user with, remove splash view. For example (in Swift):
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if !AppSession.currentSession().isLoggedIn() {
presentLoginViewController(false, completion: { ()->Void in
self.removeSplash()
})
}
else {
removeSplash()
}
// some code...
}
private func removeSplash() {
if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
appDelegate.removeSplashView()
}
}