2

I am learning iOS and developing my first iPone app. I want to add a feature to my app: if a user has login before, I want to redirect the user to the main view. otherwise, I want to redirect the user to the login view.

I have read ios change storyboard default view controller at run time, but I am wondering whether I can write the code that decides the root view in AppDelegate. Therefore, I won't have a view that is never launched.

this is my code in AppDelegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
     (UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];


    MainViewController *rootVC = [[MainViewController alloc] init];
    if (userNeverLogin) {
       LoginViewController *rootVC = [[LoginViewController alloc] init];
    }

    self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:rootVC];
    return YES;
}

this code doesn't work (it will not trigger any error, but it will show nothing in the simulator). how should I revise it? Or it's impossible to do this feature in AppDelegate?

I am sorry that I am a newbie to iOS. I hope this question is not stupid.

Community
  • 1
  • 1
Brian
  • 30,156
  • 15
  • 86
  • 87

6 Answers6

3

I would try putting the entire initialization of the view controller you want displayed into an if-else statement. You were setting rootVC to type MainViewController and then if the user had not logged in, trying to change rootVC to type LoginViewController

For example

id rootVC = nil;    
if (userNeverLogin) {
   rootVC = [[LoginViewController alloc] init];
} else {
   rootVC = [[MainViewController alloc] init];
}

self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:rootVC];

Update for view not displaying

If you haven't created the method for initializing the view controller with the nib name (what others are suggesting you do), there is another workaround. Click on your MainViewController.xib and in the Interface Builder click on File Owner. Click on the 3rd icon from the left in the utility side bar (right side of the screen), Identity Inspector, and change the custom class to MainViewController. Do the same thing for your LoginViewController.xib

brightintro
  • 1,016
  • 1
  • 11
  • 16
  • I wrote my code as this in the beginning, but XCode would say the "rootVC" in the last line is an undeclared identifier. this code can not be compiled. I think the way X Slash uses is correct. However, I also want to know why XCode treats rootVC as "undeclared identifier" in this situation. – Brian Nov 29 '12 at 06:29
  • X Slash had the right approach, edited my answer to correct this problem – brightintro Nov 29 '12 at 07:16
  • is there any way to achieve my goal without using xib? i am using storyboard, and I don't want to use xib if it's not necessary. thanks sincerely. – Brian Nov 30 '12 at 04:32
  • just open the storyboard and click on **MainViewController**, then click on **File Owner**. Same steps as listed above after that. (Identity Inspector -> change custom class) – brightintro Nov 30 '12 at 05:54
  • I have found out the solution and answered the question by myself. Maybe you can have a look at the answer I posted. I hope the answer is also useful for you. thank you anyway! – Brian Nov 30 '12 at 07:03
3

I finally found out the answer from @followben in Conditionally start at different places in storyboard from AppDelegate is actually the one I want. this is sample code from him:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{        
    BOOL isLoggedIn = ...;    // from your server response

    NSString *segueId = isLoggedIn ? @"MainIdentifier" : @"LoginIdentifier";
    self.window.rootViewController = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:segueId];

    return YES;
}

the way to set view controller identifier: enter image description here

I gave both @ekims and @X Slash a +1 for your inspiring discussion. thank you guys sincerely.

Community
  • 1
  • 1
Brian
  • 30,156
  • 15
  • 86
  • 87
2

In your code,

MainViewController *rootVC = [[MainViewController alloc] init];
if (userNeverLogin) 
{
   LoginViewController *rootVC = [[LoginViewController alloc] init];
}
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:rootVC];

rootVc will always be of MainViewController, because if the userNeverLogin is true, the rootVC inside that if block is for that if block scope only, so do something like

id rootViewController = nil;
if (userNeverLogin)
{
    rootViewController = [[LoginViewController alloc] init];
}
else
{
    rootViewController = [[MainViewController alloc] init];
}
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
X Slash
  • 4,133
  • 4
  • 27
  • 35
  • thank you! now I can get NSLog from viewDidLoad in MainViewController, however, nothing appeared in the simulator. how should i fix this problem? (screen shot of simulator: http://cl.ly/image/1A1U1y0F1p04) btw, I am using storyboard. – Brian Nov 29 '12 at 07:24
0

Try this if your View loading from Nib.

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
         (UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];



        if (userNeverLogin) {
           LoginViewController *rootVC = [[LoginViewController alloc] nitwithNibName:@"LoginViewController" Bundle:nil];
        }
else
 MainViewController *rootVC = [[MainViewController alloc] initwithNibName:@"MainViewController" Bundle:nil];

    UINavigationcontroller *nvc= = [[UINavigationController alloc] initWithRootViewController:rootVC];
        self.window.rootViewController=nvc;
        return YES;
    } 
Siba Prasad Hota
  • 4,779
  • 1
  • 20
  • 40
0

Deciding the root view controller in the App delegate should work.

I think what you missing is in

 MainViewController *rootVC = [[MainViewController alloc] init];

Try initializing the controller like this

 MainViewController *rootVC = [[MainViewController alloc] initWithNibName:@"nibFileName" bundle:nil];
Adithya
  • 4,545
  • 3
  • 25
  • 28
0
Follow this Steps:

1>keep your LoginView as a rootView       
2>In View viewDidAppear of LoginView check this
-(void)viewDidAppear:(BOOL)animated{
   [super viewDidAppear:animated];
   if ([User isLogin] == YES) {
   MainViewController *viewC = [[MainViewController alloc]     initWithNibName:@"EditStoreViewController" bundle:nil];
   [self.navigationController pushViewController:viewC animated:YES];
}

}

this will solve your problem

Banker Mittal
  • 1,918
  • 14
  • 26