Trevor Gehman Trevor Gehman - 3 months ago 123
iOS Question

Best practices for Storyboard login screen, handling clearing of data upon logout

I'm building an iOS app using a Storyboard. The root view controller is a Tab Bar Controller. I'm creating the login/logout process, and it's mostly working fine, but I've got a few issues. I need to know the BEST way to set all this up.

I want to accomplish the following:

  1. Show a login screen the first time the app is launched. When they login, go to the first tab of the Tab Bar Controller.

  2. Any time they launch the app after that, check if they are logged in, and skip straight to the first tab of the root Tab Bar Controller.

  3. When they manually click a logout button, show the login screen, and clear all the data from the view controllers.

What I've done so far is set the root view controller to the Tab Bar Controller, and created a custom segue to my Login view controller. Inside my Tab Bar Controller class, I check whether they are logged in inside the
method, and a perform the segue:
[self performSegueWithIdentifier:@"pushLogin" sender:self];

I also setup a notification for when the logout action needs to be performed:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logoutAccount) name:@"logoutAccount" object:nil];

Upon logout, I clear the credentials from the Keychain, run
[self setSelectedIndex:0]
and perform the segue to show the login view controller again.

This all works fine, but I'm wondering: should this logic be in the AppDelegate? I also have two issues:

  • The first time they launch the app, the Tab Bar Controller shows briefly before the segue is performed. I've tried moving the code to
    but the segue will not work that early.

  • When they logout, all the data is still inside all the view controllers. If they login to a new account, the old account data is still displayed until they refresh. I need a way to clear this easily on logout.

I'm open to reworking this. I've considered making the login screen the root view controller, or creating a navigation controller in the AppDelegate to handle everything... I'm just not sure what the best method is at this point.


Here is what I ended up doing to accomplish everything. The only thing you need to consider in addition to this is (a) the login process and (b) where you are storing your app data (in this case, I used a singleton).

Storyboard showing login view controller and main tab controller

As you can see, the root view controller is my Main Tab Controller. I did this because after the user has logged in, I want the app to launch directly to the first tab. (This avoids any "flicker" where the login view shows temporarily.)


In this file, I check whether the user is already logged in. If not, I push the login view controller. I also handle the logout process, where I clear data and show the login view.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

    // Show login view if not logged in already
    if(![AppData isLoggedIn]) {
        [self showLoginScreen:NO];

    return YES;

-(void) showLoginScreen:(BOOL)animated

    // Get login screen from storyboard and present it
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    LoginViewController *viewController = (LoginViewController *)[storyboard instantiateViewControllerWithIdentifier:@"loginScreen"];
    [self.window makeKeyAndVisible];
    [self.window.rootViewController presentViewController:viewController

-(void) logout
    // Remove data from singleton (where all my app data is stored)
    [AppData clearData];

   // Reset view controller (this will quickly clear all the views)
   UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
   MainTabControllerViewController *viewController = (MainTabControllerViewController *)[storyboard instantiateViewControllerWithIdentifier:@"mainView"];
   [self.window setRootViewController:viewController];

   // Show login screen
   [self showLoginScreen:NO];



Here, if the login is successful, I simply dismiss the view and send a notification.

-(void) loginWasSuccessful

     // Send notification
     [[NSNotificationCenter defaultCenter] postNotificationName:@"loginSuccessful" object:self];

     // Dismiss login screen
     [self dismissViewControllerAnimated:YES completion:nil];