2010-08-24 15 views
36

viewWillAppear, non viewDidAppear essere chiamato, non sparando

Sintomo (Questo è sia domanda e risposta in quanto c'è voluto un bel po 'di scavare per trovare la vera risposta.): viewWillAppear, viewDidAppear non venivano chiamati nella mia UIViewController .

Causa: l'incorporamento di UINavigationController o UITabBarController (il mio caso) in un UIViewController interrompe in qualche modo con la chiamata di questi metodi.

Soluzione: chiamarli manualmente nello UIViewController che contiene il già citato UINavigationController/UITabBarController.

Per esempio (supponendo projectNavigationController è la tua UINavigationController):

 
-(void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 
    [projectNavigationController viewWillAppear:animated]; 
} 

-(void)viewWillDisappear:(BOOL)animated { 
    [super viewWillDisappear:animated]; 
    [projectNavigationController viewWillDisappear:animated]; 
} 

-(void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:animated]; 
    [projectNavigationController viewDidAppear:animated]; 
} 

-(void)viewDidDisappear:(BOOL)animated { 
    [super viewDidDisappear:animated]; 
    [projectNavigationController viewDidDisappear:animated]; 
} 

Nel mio caso ho avuto un interno UITabBarController e ho chiamato i metodi di conseguenza e tutto è stato risolto.

(Attribuzione sulla soluzione: http://davidebenini.it/2009/01/03/viewwillappear-not-being-called-inside-a-uinavigationcontroller/)

+1

solo perché sono curioso ...: perché dovresti avvolgere un controller barra di registro in un altro viewcontroller? :) nella maggior parte dei casi, sono la radice della gerarchia vista (controller) ... – Toastor

+0

+1 .. risolto davvero il mio problema .. applausi –

risposta

9

ho intenzione di andare avanti e non essere d'accordo con @ St3fan, e utilizzare UIKit come contro-esempio.

Tuttavia, la saggezza (o la sua mancanza) dei controller di incorporamento in generale dovrebbe essere guidata da sani principi di progettazione dell'interfaccia utente.

Il metodo più semplice contro-esempio è UINavigationControllers incorporato in UITabBarControllers. Questi appaiono dappertutto. Appena in cima alla mia testa, l'app iPod su iPhone e i Contatti all'interno dell'app Telefono su iPhone.

Ero abbastanza curioso di preoccuparmi di controllare cosa fanno con le viste (aggiungere alla vista "super-controller" o allo UIWindow. Ero abbastanza sicuro che stavo andando a scoprire che le vedute del sottocontrollo erano discendenti delle viste del super controller nella gerarchia della vista, che è contrario alla raccomandazione di St3fan.

Ho montato un'app per iPhone molto veloce collegando tutto in InterfaceBuilder per creare un'applicazione basata su UITabBarController con due schede, la prima delle quali era a UINavigationController con un semplice UIViewController come controller di visualizzazione radice e una seconda scheda con un semplice vecchio UIViewController solo così ho avuto una seconda scheda per fare clic più tardi.

Sprinkle in alcuni NSLog dichiarazioni uscita vari UIView's per i controllori vediamo questo:

tabBarController.view = <UILayoutContainerView: 0x5b0dc80; ... 
navigationController.view = <UILayoutContainerView: 0x59469a0; ... 
rootViewController.view = <UIView: 0x594bb70; ... 
Superview: <UIViewControllerWrapperView: 0x594cc90; ... 
Superview: <UINavigationTransitionView: 0x594a420; ... 
Superview: <UILayoutContainerView: 0x59469a0; ... // navigationController.view 
Superview: <UIViewControllerWrapperView: 0x594b430; ... 
Superview: <UITransitionView: 0x5b0e110; ... 
Superview: <UILayoutContainerView: 0x5b0dc80; ... // tabBarController.view 
Superview: <UIWindow: 0x5942a30; ... 

Le linee prefisso "Superview" erano l'output risalendo la catena rootViewController.view's superview fino a colpire nullo.

Quindi, ovviamente, una rapida occhiata allo stack di chiamate in un paio di punti in cui viewDidDisappear veniva chiamato sul controller della vista radice.

Innanzitutto, lo stack di chiamata quando viewDidDisappear viene chiamato nel controller principale come risultato di un nuovo controller di essere spinto nello stack:

-[RootController viewDidDisappear:] 
-[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:] 
... 

secondo luogo, lo stack di chiamata quando un'altra scheda viene selezionata nella più in alto UITabBarController:

-[RootController viewDidDisappear:] 
-[UINavigationController viewDidDisappear:] 
-[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:] 

Quindi, in tutti i casi, sembra che Apple ha deciso che i titolari dovrebbero essere chiamando i vari viewDidAppear, ecc metodi sui loro sub-console incorporati e che della vista devono essere incorporati simile LY. Penso che l'OP abbia colpito proprio questo chiodo sulla testa se vogliamo prendere il design UIKit come un buon esempio da seguire.

+0

Interessante analisi imaginaryboy. Apprezzo il tuo POV St3fan. Nelle configurazioni tipiche, UITabBarController (che ha i propri controller di navigazione e controller di visualizzazione) viene aggiunto alla finestra. È molto facile vederlo. Tuttavia, la mia situazione era leggermente diversa. Nel mio caso l'utente inserisce una modalità specifica dell'applicazione tramite una modale. In questa altra modalità, c'è un UITabBarController diverso da quello che l'utente vede in origine. Forse avrei potuto chiamare il delegato dell'app per aggiungere il nuovo UITabBarcontroller alla finestra (?) Ma aggiungerlo al modal UIViewController era più facile. – pschang

0

Ho appena visto questa stessa circostanza. In precedenza il passaggio del generatore di interfaccia innescato da una selezione di celle della tabella aveva smesso di funzionare e dopo un po 'di esasperazione nel codice, l'ho impostato manualmente, richiamando l'override della selezione della cella nella delegazione della vista tabella.

Successivamente ho apportato alcune modifiche al layout nel controller di visualizzazione chiamato e ho visto che viewDidAppear non veniva chiamato, come descritto sopra. L'output di debug fatto riferimento a "operazioni push nidificati" o qualcosa del genere, e da quando ho avuto un grande commento a me stesso nella mia operazione spinta manuale

#warning I SHOULD NOT HAVE TO DO THIS!!

ho breakpointed il codice segue e, abbastanza sicuro, l'segue IB ora funzionava, ed era la mia operazione manuale nel codice di selezione della cella della tabella che stava rovinando le chiamate delegate nella vista chiamata. Ho rimosso il codice manuale e tutto va bene di nuovo.

Sembra strano che il codice di selezione cella venga chiamato dopo che la vista è stata inviata. Devo fare un protocollo e delegare per ottenere il percorso dell'indice della cella selezionata nel chiamante.

Problemi correlati