JasonGenX
JasonGenX

Reputation: 5444

Dynamic first View Controller in iOS

I am having a little chicken/egg problem in understanding how the first view controller is chosen, and how it can change dynamically.

In a typical login based application (e.g. facebook) you have a first view controller that's the login. Once you've logged in, another view is first the next time you enter the application.

I can't see one place (in main.m?) or the app delegate where you can choose the first view and apply some logic to choosing it. What I have seen, is how a first view is used anyway, and within that view some logic is done whether or not to invoke the login window. Is that the only practice to get this done? I don't want my main view flashing for a moment before it spawns a login view in case the user needs to login. Can't I just go directly to the login view if needed, or to the 'logged in' view first, if the user is already logged in?

Upvotes: 3

Views: 2050

Answers (2)

wattson12
wattson12

Reputation: 11174

You can do this in any number of ways, but the simplest is to keep some record of wether the user needs to login, and if they do, present a login view controller as a modal view controller over the top of your standard root view controller

- (void)appDidFinishLaunchingWithOptions:(NSDictionary *)options
{
    //window setup

    UIViewController *normalRootViewController = [[UIViewController alloc] init];
    self.window.rootViewController = normalRootViewController;

    [self.window makeKeyAndVisible];

    if (shouldDisplayLoginViewController)
    {
        UIViewController *loginViewController = [[UIViewController alloc] init];
        [self.window.rootViewController presentModalViewController:loginViewController animated:NO];
    }
}

When you want to remove the login view controller and show the normal view controller, just dismiss it like any modal view controller

Upvotes: 0

A-Live
A-Live

Reputation: 8944

In the app delegate you have the window var which is supposed to be the main application window:

self.window.rootViewController = anyViewController;
[self.window makeKeyAndVisible];

What you'll need to do is to decide what is the instance of anyViewController. Normally you avoid 'flashing' by presenting the splash image, it is displayed until the key window get's visible with it's root view controller. Now what you can do is something like:

main.m

int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class]));
    }
}

MyAppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    UserInfo * appUserInfo = [[DataManager sharedManager] applicationUserInfo];
    UIViewController *anyViewController = [[ControllersManager sharedManager] launchViewControllerForUser:userInfo];

    self.window.rootViewController = anyViewController;
    [self.window makeKeyAndVisible];
    return YES;
}

Where ControllersManager is a singleton controller's manager which you'll want to use for all navigation operations. The method launchViewControllerForUser: could be the following:

-(UIViewController*) launchViewControllerForUser:(UserInfo*) aUserInfo {
   if (aUserInfo) {
       return [[MainMenuViewController new] autorelease];
   } else {
       return [[LoginViewController new] autorelease];
   }
}

And DataManager is a singleton class which you'll use for all data operations such as read the previously saved application user wrapped in UserInfo object.


Sometimes you do have a nib file for the main window, if you want to use such technique you'll need to customize the line

    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

with the same pattern:

    self.window = [[WindowManager sharedManager] keyLaunchApplicationWindow];

And inside this method you can also assign the root navigation controller. So you can actually combine this two approaches.

The main idea is to prepare the orchestrating managers to keep everything organized.

Upvotes: 2

Related Questions