J'ai cherché une solution sur Internet. Je n'ai rien trouvé. Donc: j'utilise un UINavigationController. J'y pousse deux UIViewControllers. Dans le second ViewController poussé, j'exécute ce code:
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error {
NSLog([error localizedDescription]);
[self.navigationController popViewControllerAnimated:YES]; }
La chose attendue serait que le dernier ViewController poussé disparaisse. Dans cette application, je fais cela à quelques endroits et cela fonctionne bien partout dans ce ViewController. Ce qui se passe, c'est que seul le bouton Précédent s'éteint (animé) mais tout le reste reste à l'écran. Dans la sortie de la console, deux choses sont imprimées lorsque cette ligne s'exécute:
2011-03-14 16: 32: 44.580 L'animation pop imbriquée TheAppXY [18518: 207] peut entraîner une barre de navigation corrompue
2011-03-14 16: 32: 53.507 TheAppXY [18518: 207] Fin d'une transition de navigation dans un état inattendu. L'arborescence des sous-vues de la barre de navigation peut être corrompue.
Deux messages d'erreur sur lesquels je n'ai trouvé AUCUNE information. J'utilise XCode 4 et iOS SDK 4.3. Peut-être que n'importe qui peut m'aider avec ce problème.
Je suis tombé sur une situation similaire dans mon code et le message dit:
l'animation Push imbriquée peut entraîner une barre de navigation corrompue
Fin d'une transition de navigation dans un état inattendu. La sous-arborescence de la barre de navigation> peut être corrompue.
Ma conclusion à ce problème était que je poussais 2 contrôleurs de vue l'un après l'autre en succession rapide et les deux étaient animés.
Dans votre cas, il semble que vous puissiez faire apparaître plusieurs contrôleurs de vue avec animation les uns après les autres.
Par conséquent, pendant qu'une vue est en cours d'animation, vous ne devez pas démarrer l'animation sur une autre vue.
J'ai également constaté que si je désactivais l'animation sur une vue, le message d'erreur disparaissait.
Dans mon cas, c'était un problème avec la logique de flux car je n'avais pas l'intention de pousser 2 contrôleurs de vue l'un après l'autre. L'un était poussé dans la logique du boîtier de commutation et un autre après sa fin.
J'espère que cela aide quelqu'un.
Vous pouvez l'obtenir à tout moment que vous essayez de faire apparaître avant viewDidAppear
. Si vous définissez un indicateur, vérifiez simplement cet indicateur dans viewDidAppear
, vous n'aurez pas de problème.
J'ai créé un remplacement sans rendez-vous pour UINavigationController qui mettra les animations en file d'attente pour vous et évitera complètement ce problème.
Récupérez-le dans BufferedNavigationController
J'ai aussi eu ce problème, et voici ce qui causait le mien:
Ma solution? J'ai resserré mes instructions if ... then et renoncé à l'exécution de tout code dans mes IBActions UISegmentedControl lorsque selectedSegmentIndex == -1.
Je ne sais toujours pas pourquoi j'ai eu des erreurs d'animation "pop" et non des erreurs "Push", mais au moins j'ai compris mon erreur et je l'ai réparée!
J'espère que ceci aide quelqu'un d'autre!
Ce problème se produit avec moi lorsque j'utilise des storyboards. J'ai fait une erreur: j'ai un UIButton avec une action pour effectuerSegueWithIdentifier. Donc, je relie le Push segue avec Button avec l'autre ViewController donc ce problème se produit.
Pour résoudre: liez l'action du bouton dans UIButton et liez la séquence Push entre deux ViewControllers.
La combinaison des réponses de MilGra et d'Andrew m'a donné quelque chose qui fonctionne de manière fiable et est un remplacement simple de UINavigationController.
Cela améliore la réponse de MilGra pour le faire fonctionner avec des push et des pops, mais est plus simple que BufferedNavigationController d'Andrew. (En utilisant BufferedNavigationController, je recevais parfois des transitions qui ne se termineraient jamais et ne montreraient qu'un écran noir.)
Tout cela ne semble pas nécessaire sur iOS8, mais était toujours nécessaire pour moi sur 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
oui, malheureusement Apple n'a pas synchronisé les animations de UINavigationController. La solution d'Andrew est excellente, mais si vous ne voulez pas couvrir toutes ses fonctionnalités, il existe une solution plus simple, remplacez ces deux méthodes:
// 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 ];
}
et créez une variable d'instance NSMutableArray appelée waitList, et vous avez terminé.