2013-08-14 14 views
9

Um meinen Anmeldebildschirm anzuzeigen, wenn die Anwendung geladen wird, und nicht nachdem der Benutzer sich anmeldet, habe ich entschieden, ein Authentifizierungsobjekt in NSUserDefaults hinzuzufügen, wenn sich der Benutzer erfolgreich anmeldet. Wenn die App gestartet wird, ist dieser Auth-Parameter aktiviert und der View-Controller ist entsprechend eingestellt (wenn der Benutzer auth ist, wird ein Feed angezeigt, wenn nicht, wird ein Login-Bildschirm angezeigt). Im letzteren Fall habe ich die App delegieren Sie den Stammansicht-Controller auf den Feed zurück, nachdem der Benutzer sich angemeldet hat. Ist dies eine schlechte Vorgehensweise oder gibt es eine bessere Möglichkeit, dies zu tun?Ändern des Stammansicht-Controllers, nachdem die iOS-App geladen wurde.

Im AppDelegate:

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

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 

    if([[defaults objectForKey:@"auth"] isEqualToNumber:[NSNumber numberWithInt:1]]){ 
     self.window.rootViewController = deckController; 
    }else{ 
     UIStoryboard *sb = [UIStoryboard storyboardWithName:@"MainStoryboard" 
               bundle:nil]; 
     UIViewController* vc = [sb instantiateViewControllerWithIdentifier:@"loginViewController"]; 
     self.window.rootViewController = vc; 
    } 
    [self.window makeKeyAndVisible]; 
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:NO]; 
    return YES; 
} 

- (void) setRoots 
{ 
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    IIViewDeckController* deckController = [self generateControllerStack]; 
    self.rightController = deckController.rightController; 
    self.centerController = deckController.centerController; 
    self.window.rootViewController = deckController; 
    [self.window makeKeyAndVisible]; 
} 

Im Login-View-Controller:

- (IBAction)loginClick:(id)sender { 
    if([_emailField.text length]>0&&[_passField.text length]>0){ 
     NSString *user = _emailField.text; 
     NSString *pass = _passField.text; 
     [[API sharedInstance] login:user andPass:pass onCompletion:^(NSDictionary *json){ 
      NSLog(@"%@", json); 
      if(![json objectForKey:@"error"]){ 
       [API sharedInstance].authorized = 1; 
       NSNumber *auth = [NSNumber numberWithInt:1]; 
       NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
       [defaults setObject:auth forKey:@"auth"]; 
       [defaults synchronize]; 

       captureYouAppDelegate *app = [[UIApplication sharedApplication] delegate]; 
       [app setRoots]; 
      }else{ 
       [API sharedInstance].authorized = 0; 
      } 
     }]; 
    }else{ 
     if([_emailField.text length]<1){ 
      [_emailField becomeFirstResponder]; 
     }else{ 
      [_passField becomeFirstResponder]; 
     } 
    } 
} 

Ich frage mich, ob es eine bessere oder einfachere Weise, als das zu tun. Vielen Dank!

+0

, warum Sie nicht einen einfachen 'UINavigationController' als' rootViewController' hinzufügen und nicht nur tun Wenn der Benutzer sich bereits angemeldet hat, drücken Sie den Anmeldebildschirm in den Navigationsstapel.es wäre viel einfacher und viel eleganter als Ihre derzeitige Lösung. – holex

+0

@holex Wenn die Tableiste auch nach dem Einloggen benötigt wird, wäre das Hinzufügen eines UINavigationControllers keine Option, oder? – Donald

Antwort

4

Ich glaube nicht zurückgesetzt window.rootViewController ist eine schlechte Praxis. Es ist jedoch nicht erforderlich, ein Fenster neu zu erstellen.
Wenn Sie den vorherigen View-Controller nicht verwenden möchten, ersetzen Sie einfach die rootViewController des Fensters durch den neuen View-Controller. Wenn Sie zu Ihrem früheren View-Controller zurückkehren möchten, verwenden Sie -presentViewController: animated: completion:, um Ihren View-Controller als bessere Alternative darzustellen.

+0

Wenn ich es einfach ersetze, kann ich die IIViewDeckController-Eigenschaften nicht festlegen. –

+0

Ich stimme damit überein, das Ändern des rootViewControllers zur Laufzeit ist ein sehr schlechtes Code-Muster. – holex

+1

@holex Könntest du bitte erklären, warum es ein sehr schlechtes Code-Muster ist? Danke! – Donald

0

Es gibt keine Notwendigkeit, alloc Fenster wieder können Sie direkt das Set

window.rootViewController = yourVC; 
5

Nur um zu klären. Ich hatte den rootViewController von UIWindow zuvor ohne Probleme zurückgesetzt, aber als ich dies versuchte, während ich die Geräte-Rotation zuließ, stieß ich auf einige Probleme - Rotation hörte einfach auf zu arbeiten.

Ich fand das folgende direkt aus Apples Dokumentation beim Debuggen. Der folgende Link enthält eine Reihe von Richtlinien zum Arbeiten mit UIWindow. Diese beziehen sich alle auf die Gerätedrehung, sind aber immer noch gut zu wissen.

Kurze Antwort, verwenden Sie einen Root-Controller und fügen Sie untergeordnete Ansicht Controller hinzu. Sie können dann die untergeordneten VCs problemlos austauschen.

• Sie haben die UIView-Eigenschaft des View-Controllers als Unteransicht zu UIWindow hinzugefügt.

Entwickler werden davon abgeraten, die View-Eigenschaft eines beliebigen View-Controllers als Unteransicht von UIWindow hinzuzufügen. Der Root-View-Controller Ihrer Anwendung sollte entweder im Interface Builder oder zur Laufzeit vor dem Zurückkehren aus der Anwendung der rootViewController-Eigenschaft des Anwendungsfensters zugewiesen werden: didFinishLaunchingWithOptions :. Wenn Sie Inhalte von mehreren View-Controllern gleichzeitig anzeigen müssen, sollten Sie einen eigenen Container-Ansichten-Controller definieren und diesen als Root-View-Controller verwenden. Siehe Erstellen benutzerdefinierter Containeransichts-Controller.

Überprüfen Sie this technical Q&A für weitere Details.

0

Schritt für Schritt i die gute Praxis zeigt,

mit Hilfe von UINavigationController von RootViewController verwenden
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    // Override point for customization after application launch. 

    self.splash = [[SplashViewController alloc] initWithNibName: @"SplashViewController" bundle: nil]; 
    self.window.rootViewController = self.splash; 
    [self.window makeKeyAndVisible]; 
    DLog(@"finished initializing ....."); 
    [self setRootViewController]; 

    return YES; 
} 



- (void) setRootViewController 
{ 
    DLog(@"setRootViewController"); 
    if (self.sessionManager.isLoggedIn) 
    { 
      [self navigateToHomeController]; 

    } else { 
      [self navigateToLoginController]; 
     } 
} 


- (void) navigateToHomeController 
{ 
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"kStoryBoard" bundle: nil]; 
    UINavigationController* homeNavigationController = [storyboard instantiateViewControllerWithIdentifier:@"kHomeNavController"]; 
    NSArray* controllers = [homeNavigationController viewControllers]; 
    if([controllers lastObject]) 
    { 
     if ([[controllers objectAtIndex:0] isKindOfClass:[HomeViewController class]]) { 
      HomeViewController* homeController = (HomeViewController*) [controllers objectAtIndex:0]; 
      self.window.rootViewController = [[OLNavigationViewController alloc] initWithRootViewController: homeController]; 
     } 
    } 
} 



- (void) navigateToLoginController 
{ 
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"kStoryBoard" bundle: nil]; 
    UINavigationController* loginNavigationController = [storyboard instantiateViewControllerWithIdentifier:@"kLoginNavController"]; 
    if ([loginNavigationController isKindOfClass:[OLLoginViewController class]]) { 
     OLLoginViewController* loginController = (OLLoginViewController*) loginNavigationController; 
     loginController.shouldHideToolBar = YES; 
     self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController: loginController]; 
    } 
} 
Verwandte Themen