2013-08-14 5 views
9

Per visualizzare la schermata di accesso quando viene caricata l'app, e non dopo che l'utente ha effettuato l'accesso, ho deciso di aggiungere un oggetto auth in NSUserDefaults quando l'utente ha effettuato l'accesso. Quando l'app viene avviata, il parametro auth viene controllato e il controller della vista viene impostato di conseguenza (se l'utente è auth mostrerà un feed, altrimenti visualizzerà una schermata di accesso) In quest'ultimo caso, ho l'app delegato reimposta il controller della vista radice sul feed dopo che l'utente ha effettuato l'accesso. È una cattiva pratica o esiste un modo migliore per farlo?Modifica del controller di visualizzazione radice dopo il caricamento dell'applicazione iOS.

Nel app delegato:

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

Nella login vista del regolatore:

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

Mi chiedo se c'è un modo migliore o più facile di farlo. Grazie!

+0

perché non aggiungi un semplice '' UINavigationController' come rootViewController', e basta non spingere la schermata di accesso nello stack di navigazione se l'utente ha già effettuato l'accesso.sarebbe molto più semplice e molto più elegante della tua attuale soluzione. – holex

+0

@holex Se la barra delle schede è necessaria anche dopo l'accesso, aggiungere un UINavigationController non sarebbe un'opzione, giusto? – Donald

risposta

4

Non credo che il reset del window.rootViewController sia una cattiva pratica. Tuttavia, non è necessario ricreare una finestra.
Se non si desidera utilizzare il controller di visualizzazione precedente, è sufficiente sostituire lo rootViewController della finestra con il nuovo controller di visualizzazione. Se si desidera tornare al controller di visualizzazione precedente, utilizzare -presentViewController: animated: completion: per presentare il controller di visualizzazione potrebbe essere un'alternativa migliore.

+0

La semplice sostituzione non mi consente di impostare le proprietà IIViewDeckController. –

+0

Sono d'accordo, cambiare il rootViewController durante il runtime è un modello di codice molto scadente. – holex

+1

@holex Potresti spiegare perché è un modello di codice molto scadente? grazie! – Donald

0

Non v'è alcuna necessità di finestra alloc ancora una volta è possibile impostare direttamente questo

window.rootViewController = yourVC; 
5

tanto per chiarire. Avevo reimpostato il rootViewController di UIWindow prima senza alcun problema, ma quando provavo a farlo mentre permettevo la rotazione del dispositivo mi sono imbattuto in alcuni problemi - La rotazione ha smesso di funzionare.

Ho trovato quanto segue direttamente dai documenti di Apple durante il tentativo di eseguire il debug. Il link sottostante ha una serie di linee guida su come lavorare con UIWindow. Questi sono tutti correlati alla rotazione del dispositivo, ma comunque utili.

Risposta breve, utilizzare un controller di root e aggiungere controller di visualizzazione figlio. È quindi possibile scambiare i VC figlio senza alcun problema.

• È stata aggiunta la proprietà UIView del controller di visualizzazione a UIWindow come sottoview.

Gli sviluppatori sono scoraggiati dall'aggiungere la proprietà di visualizzazione di qualsiasi controller di visualizzazione come subview di UIWindow. Il controller della vista radice dell'applicazione deve essere assegnato alla proprietà rootViewController della finestra dell'app in Builder interfaccia o in runtime prima di tornare dall'applicazione: didFinishLaunchingWithOptions :. Se è necessario visualizzare il contenuto da più di un controller di visualizzazione contemporaneamente, è necessario definire il proprio controller di visualizzazione del contenitore e utilizzarlo come controller della vista principale. Vedere Creazione di controller di visualizzazione contenitori personalizzati.

Verificare this technical Q&A per ulteriori dettagli.

0

Passo dopo passo sto mostrando la buona pratica utilizzare della RootViewController con l'aiuto di 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]; 
    } 
} 
Problemi correlati