iOS: comportamiento inesperado de popViewController

He estado buscando en Internet una solución. No hay nada que pueda encontrar. Entonces: estoy usando un UINavigationController. Estoy presionando a dos UIViewControllers en él. En el segundo empujado ViewController estoy ejecutando este código:

- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error { NSLog([error localizedDescription]); [self.navigationController popViewControllerAnimated:YES]; } 

Lo que se espera que suceda sería que el último ViewController empujado desaparece. En esta aplicación, estoy haciendo esto en pocos lugares y funciona bien en todas partes, en este mismo ViewController. Lo que sucede es que solo el button de retroceso se apaga de la pantalla (animado), pero todo lo demás permanece en la pantalla. En la Salida de console, dos cosas se imprimen cuando se ejecuta esta línea:

2011-03-14 16: 32: 44.580 TheAppXY [18518: 207] animation anidada anidada puede dar como resultado una barra de navigation dañada

2011-03-14 16: 32: 53.507 TheAppXY [18518: 207] Finalizando una transición de navigation en un estado inesperado. El tree de subview de la barra de navigation podría dañarse.

Dos posts de error No pude encontrar CUALQUIER información. Estoy usando XCode 4 y iOS SDK 4.3. Quizás alguien pueda ayudarme con este problema.

Encontré una situación similar en mi código y el post decía:

La animation de inserción anidada puede dar como resultado una barra de navigation dañada.

Finalizando una transición de navigation en un estado inesperado. Barra de navigation subview tree> podría dañarse.

Mi conclusión a este problema fue que estaba empujando 2 controlleres de vista uno tras otro en rápida sucesión y ambos estaban animados.

En su caso, parece que podría estar apareciendo varios controlleres de vista con animation uno tras otro.

Por lo tanto, mientras una vista está siendo object de animation, no debe iniciar la animation en otra vista.

También encontré que si deshabilitaba la animation en una vista, el post de error desaparecía.

En mi caso, fue un problema con la lógica de flujo, ya que no tenía la intención de impulsar 2 controlleres de vista uno tras otro. Uno estaba siendo empujado dentro de la lógica del caso del interruptor y otro después de su final.

Espero que esto ayude a alguien.

Puede get esto en cualquier momento que intente viewDidAppear antes de viewDidAppear . Si configura un indicador, simplemente marque ese indicador en viewDidAppear , no tendrá problemas.

He creado un reemploop para UINavigationController que pondrá en queue tus animaciones y evitará por completo este problema.

Cómprelo desde BuffenetworkingNavigationController

Tuve este problema también, y esto es lo que estaba causando el mío:

  1. En RootViewController, estoy usando varios objects UISegmentedControl para determinar cuál de las muchas vistas cargar después.
  2. En esa vista (sub / segundo), estaba apareciendo (usando el button "Atrás") de nuevo a RootViewController.
  3. En RootViewController, manejaba viewWillAppear para "reiniciar" cada uno de mis objects UISegmentedControl a un SelectedSegmentIndex de -1 (lo que significa que ningún segmento parece "presionado").
  4. Ese "reinicio" desencadenó cada uno de mis objects UISegmentedControl para activar sus IBActions asociadas (y separadas).
  5. Como no estaba manejando para una "selección" de -1, tuve varios methods disparando al mismo time, todos intentando impulsar una vista diferente.

Mi solucion Apreté mis declaraciones de if … then y me aseguré de ejecutar cualquier código en mis IBActions de UISegmentedControl cuando selectedSegmentIndex == -1.

Todavía no estoy seguro de por qué obtuve errores de animation "pop" y no "empuje" errores, ¡pero al less descubrí mi error y lo solucioné!

¡Espero que esto ayude a alguien más!

Sí, lamentablemente Apple no sincronizó las animaciones del UINavigationController. La solución de Andrew es excelente, pero si no desea cubrir toda su funcionalidad, existe una solución más sencilla, anule estos dos methods:

 // navigation end event - ( void ) navigationController : ( UINavigationController* ) pNavigationController didShowViewController : ( UIViewController* ) pController animated : ( BOOL ) pAnimated { if ( [ waitingList count ] > 0 ) [ waitingList removeObjectAtIndex : 0 ]; if ( [ waitingList count ] > 0 ) [ super pushViewController : [ waitingList objectAtIndex : 0 ] animated : YES ]; } - ( void ) pushViewController : ( UIViewController* ) pController animated : ( BOOL ) pAnimated { [ waitingList addObject : pController ]; if ( [ waitingList count ] == 1 ) [ super pushViewController : [ waitingList objectAtIndex : 0 ] animated : YES ]; } 

y cree una variable de instancia NSMutableArray llamada waitingList, y ya está.

Este problema sucede conmigo cuando uso storyboards. Cometí un error: tengo un button UIB con una acción para ejecutar Segmente con Identificador. Por lo tanto, enlace el segue push con el button con el otro ViewController para que ocurra este problema.

Para resolver: Vincula la acción del button en el button UIB y vincula el segue entre dos ViewControllers.

La combinación de las respuestas de MilGra y Andrew me dio algo que funciona de manera confiable y es un reemploop de UINavigationController más simple.

Esto mejora la respuesta de MilGra para que funcione con pushes y pops, pero es más simple que el controller BuffenetworkingNavigation de Andrew. (Usando BuffenetworkingNavigationController, ocasionalmente recibía transiciones que nunca se completaban y solo mostraban una pantalla negra).

Todo esto parece no ser necesario en iOS8, pero aún era necesario para mí en iOS7.

 @implementation UINavigationControllerWithQueue { NSMutableArray *waitingList; } -(void) viewDidLoad { [super viewDidLoad]; self.delegate = self; // NOTE: delegate must be self! waitingList = [[NSMutableArray alloc] init]; } # pragma mark - Overrides -(void) pushViewController: (UIViewController*) controller animated: (BOOL) animated { [self queueTransition:^{ [super pushViewController:controller animated:animated]; }]; } - (UIViewController *)popViewControllerAnimated:(BOOL)animated { UIViewController *result = [self.viewControllers lastObject]; [self queueTransition:^{ [super popViewControllerAnimated:animated]; }]; return result; } - (NSArray*)popToRootViewControllerAnimated:(BOOL)animated { NSArray* results = [self.viewControllers copy]; [self queueTransition:^{ [super popToRootViewControllerAnimated:animated]; }]; return results; } # pragma mark - UINavigationControllerDelegate -(void) navigationController: (UINavigationController*) navigationController didShowViewController: (UIViewController*) controller animated: (BOOL) animated { [self dequeTransition]; } # pragma mark - Private Methods -(void) queueTransition:(void (^)()) transition { [waitingList addObject:transition]; if (waitingList.count == 1) { transition(); } } -(void) dequeTransition { if (waitingList.count > 0) { [waitingList removeObjectAtIndex:0]; } if (waitingList.count > 0) { void (^transition)(void) = [waitingList objectAtIndex:0]; if (transition) { transition(); } } } @end