xcode - bar - root view controller navigation controller
iOS: comportamiento inesperado popViewController (7)
He estado buscando en Internet una solución. No hay nada que pueda encontrar. Entonces: Estoy usando un controlador de UINavigation. Estoy presionando dos UIViewControllers en él. En el segundo ViewController presionado estoy ejecutando este código:
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error {
NSLog([error localizedDescription]);
[self.navigationController popViewControllerAnimated:YES]; }
Lo esperado es que el último ViewController presionado desaparezca. En esta aplicación, estoy haciendo esto en algunos lugares y funciona bien en cualquier lugar en este ViewController. Lo que sucede es que solo el botón Atrás se apaga (animado) pero todo lo demás permanece en pantalla. En la Salida de la consola se imprimen dos cosas cuando se ejecuta esta línea:
2011-03-14 16: 32: 44.580 La animación pop anidada de TheAppXY [18518: 207] puede resultar en una barra de navegación dañada
2011-03-14 16: 32: 53.507 TheAppXY [18518: 207] Finalizando una transición de navegación en un estado inesperado. El árbol de subvista de la barra de navegación podría dañarse.
Dos mensajes de error que no pude encontrar CUALQUIER información en. Estoy usando XCode 4 y iOS SDK 4.3. Tal vez alguien me pueda ayudar con este problema.
Encontré una situación similar en mi código y el mensaje decía:
La animación de inserción anidada puede dar como resultado una barra de navegación dañada
Terminando una transición de navegación en un estado inesperado. El árbol de subvista de la barra de navegación> puede dañarse.
Mi descubrimiento de este problema fue que estaba empujando 2 controladores de vista uno tras otro en rápida sucesión y ambos estaban animados.
En su caso, parece que podría estar abriendo varios controladores de vista con animación uno tras otro.
Por lo tanto, mientras una vista está experimentando animación, no debe iniciar la animación en otra vista.
También descubrí que si deshabilitaba la animación en una vista, el mensaje 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 empujar 2 controladores de vista uno tras otro. Uno fue empujado dentro de la lógica de la caja del interruptor y otro después de su final.
Espero que esto ayude a alguien.
Este problema me pasa cuando uso guiones gráficos. Cometí un error: tengo un UIButton con una acción para realizar Segmento con identificador. Así que vinculo el segmento de empuje con el botón con el otro ViewController para que surja este problema.
Para resolver: vincule la acción del botón en UIButton y vincule el segmento de empuje entre dos ViewControllers.
He creado un reemplazo directo para UINavigationController que pondrá en cola las animaciones para usted y evitará este problema por completo.
Cógelo de BufferedNavigationController
La combinación de las respuestas de MilGra y Andrew me dio algo que funciona de manera confiable y es un reemplazo de UINavigationController más sencillo.
Esto mejora la respuesta de MilGra para hacer que funcione con pushs y pops, pero es más simple que Andrew''s BufferedNavigationController. (Al utilizar BufferedNavigationController, ocasionalmente obtenía transiciones que nunca se completaban y solo mostraban una pantalla en negro).
Todo esto parece no ser necesario en iOS8, pero aún así fue 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
Puede obtener esto en cualquier momento que intente viewDidAppear
antes de viewDidAppear
. Si establece una viewDidAppear
, entonces solo marque esa viewDidAppear
en viewDidAppear
, no tendrá ningún problema.
Sí, desafortunadamente Apple no sincronizó las animaciones de UINavigationController. La solución de Andrew es excelente, pero si no desea cubrir toda su funcionalidad, hay una solución más simple, anule estos dos métodos:
// 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 listo.
Yo también tuve este problema, y esto es lo que estaba causando el mío:
- En RootViewController, estoy usando varios objetos UISegmentedControl para determinar cuál de las muchas vistas cargará a continuación.
- En esa vista (sub / 2nd), estaba haciendo estallar (usando el botón "Atrás") de nuevo a RootViewController.
- En RootViewController, estaba manejando viewWillAppear para "reiniciar" cada uno de mis objetos UISegmentedControl a un índice de segmento seleccionado de -1 (lo que significa que ningún segmento parece "presionado").
- Ese "reinicio" activó cada uno de mis objetos UISegmentedControl para disparar sus IBActions asociadas (y separadas).
- Como no estaba manejando para una "selección" de -1, tuve varios métodos disparando al mismo tiempo, todos tratando de empujar una vista diferente.
Mi arreglo? Ajusté mi if ... entonces las declaraciones y dejé de ejecutar cualquier código en mi UISegmentedControl IBActions cuando seleccionéSegmentIndex == -1.
Todavía no estoy seguro de por qué recibí errores de animación "pop" y no errores "push", ¡pero al menos descubrí mi error y lo solucioné!
¡Espero que esto ayude a alguien más!