2013-08-14 12 views
9

Aby wyświetlić ekran logowania po załadowaniu aplikacji, a nie po zalogowaniu się użytkownika, postanowiłem dodać obiekt uwierzytelniający w pliku NSUserDefaults, gdy użytkownik loguje się pomyślnie. Po uruchomieniu aplikacji sprawdzany jest parametr auth, a kontroler widoku jest odpowiednio ustawiony (jeśli użytkownik jest uwierzytelniony, wyświetli kanał informacyjny, jeśli nie wyświetli ekranu logowania). W tym drugim przypadku mam aplikację Deleguj zresetować kontroler widoku głównego do kanału po zalogowaniu użytkownika. Czy ta zła praktyka czy jest lepszy sposób na zrobienie tego?Zmiana kontrolera widoku głównego po załadowaniu aplikacji systemu iOS.

W app delegata:

- (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]; 
} 

W logowania widoku kontrolera:

- (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]; 
     } 
    } 
} 

Zastanawiam się, czy istnieje lepszy sposób niż lub łatwiej robić. Dziękuję Ci!

+0

dlaczego nie można dodać prosty 'UINavigationController' jako' rootViewController', a ty po prostu nie popchnij ekran logowania do stosu nawigacji, jeśli użytkownik już się zalogował.byłoby to o wiele łatwiejsze i znacznie bardziej eleganckie niż obecne rozwiązanie. – holex

+0

@holex Jeśli pasek kart jest również potrzebny po zalogowaniu, dodanie kontrolera UINavigationController nie byłoby opcją, prawda? – Donald

Odpowiedz

4

Nie sądzę, resetowanie window.rootViewController jest złe praktyki. Jednak nie ma potrzeby ponownego tworzenia okna.
Jeśli nie chcesz używać poprzedniego kontrolera widoku, po prostu zastąp okno rootViewController nowym kontrolerem widoku. Jeśli chcesz przełączyć się z powrotem do poprzedniego kontrolera widoku, użyj -presentViewController: animated: completion:, aby przedstawić kontroler widoku, który może być lepszą alternatywą.

+0

Po prostu zastąpienie go nie pozwala mi ustawić właściwości IIViewDeckController. –

+0

Zgadzam się z tym, zmiana rootViewController podczas wykonywania jest bardzo słabym wzorem kodu. – holex

+1

@holex Czy mógłbyś wyjaśnić, dlaczego jest to bardzo zły wzór kodu? dzięki! – Donald

0

Nie ma potrzeby, aby ponownie okno alloc można bezpośrednio ustawić to

window.rootViewController = yourVC; 
5

prostu do wyjaśnienia. Zresetowałem wcześniej rootViewController UIWindow bez żadnego problemu, ale gdy próbowałem to zrobić, zezwalając na rotację urządzenia, natrafiłem na pewne problemy - Rotacja właśnie przestała działać.

Znalazłem następujące bezpośrednio z dokumentów Apple podczas próby debugowania. Poniższy link zawiera wiele wskazówek dotyczących pracy z interfejsem UIWindow. Wszystkie związane są z rotacją urządzeń, ale nadal dobrze je znać.

Krótka odpowiedź, użyj kontrolera root i dodaj kontrolki widoku podrzędnego. Możesz następnie zamienić potomne VC bez problemu.

• Dodałeś właściwość UIView kontrolera widoku do interfejsu UIWindow jako podglądu.

Programiści są zniechęcani do dodawania właściwości widoku dowolnego kontrolera widoku jako podzbióra interfejsu UIWindow. Kontroler głównego widoku aplikacji powinien zostać przypisany do właściwości rootViewController okna aplikacji w Konstruktorze interfejsów lub w środowisku wykonawczym przed powrotem z aplikacji: didFinishLaunchingWithOptions :. Jeśli chcesz wyświetlać zawartość z więcej niż jednego kontrolera widoku jednocześnie, powinieneś zdefiniować własny kontroler widoku kontenera i użyć go jako kontrolera widoku głównego. Zobacz Tworzenie niestandardowych kontrolerów widoku kontenera.

Aby uzyskać więcej informacji, sprawdź numer this technical Q&A.

0

Krok po kroku pokazuję Dobrą praktyką jest stosowanie od rootviewcontroller z pomocą UINavigationController

- (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]; 
    } 
} 
Powiązane problemy