web-dev-qa-db-fra.com

problème UINavigation sur iPhone: une animation Push imbriquée peut endommager la barre de navigation

Je continue à recevoir les erreurs suivantes:

2011-04-02 14:55:23.350 AppName[42430:207] nested Push animation can result in corrupted navigation bar
2011-04-02 14:55:23.352 AppName[42430:207] nested Push animation can result in corrupted navigation bar
2011-04-02 14:55:23.729 AppName[42430:207] Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
2011-04-02 14:55:23.729 AppName[42430:207] Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.

Voici ce que je fais. À partir d'un contrôleur de vue, j'appelle le texte suivant lorsqu'un certain bouton est enfoncé:

EventsViewController *viewController = [[EventsViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
navController.navigationBar.tintColor = [UIColor blackColor];
[self presentModalViewController:navController animated:YES];
[viewController release];
[navController release];

Ensuite, si un certain bouton est enfoncé dans EventsController, j'appelle:

SingleEventViewController *viewController = [[SingleEventViewController alloc] initWithEvent:[currentEvents objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];

Ensuite, si un certain bouton est enfoncé dans SingleEventViewController, j'appelle:

EventMapView* viewController = [[EventMapView alloc] initWithCoordinates];
[[self navigationController] pushViewController:viewController animated:YES];
[viewController release];

Alors oui, il est évident qu'il existe des animations Push imbriquées, mais n'est-ce pas la bonne façon de s'y prendre? J'ai vérifié le code Apple DrillDownSave et cela semble être la façon dont ils le font. Est-il important que j'utilise des méthodes init au lieu de méthodes viewDidLoad?

69
joshholat

Je l'ai compris. Apparemment, si vous appelez -pushViewController de l'extérieur de la méthode -didSelectRowAtIndexPath d'un UITableViewDelegate, cela ne fonctionnera pas. Déplacer l'appel dans cette fonction a fonctionné. Bizarre.

10
joshholat

Appeler pushViewController avant viewDidAppear est dangereux.

118
S B

DÉCLENCHEMENT ACCIDENTEL DE LA MÊME SEGUE DEUX FOIS Une fois dans le code et une fois à partir du constructeur d'interface, mais les deux en même temps ...

J'avais la même erreur que le reste d'entre vous. Le seul problème, c’est que j’ai tiré deux fois par accident. Une fois du constructeur d'interface et une fois de mon code.

J'ai un UITableView. Lorsqu'une cellule est sélectionnée, un générateur de générateur d'interface est déclenché. Voici mon problème, j'avais la scène configurée pour être directement virée en cliquant sur la cellule elle-même, dans le constructeur d'interface, puis dans mon code, j'avais sous didSelectRowAtIndexPath, un code qui déclencherait cette même séquence ...

[self performSegueWithIdentifier:@"MySegue" sender:tableView];

Cela signifie que lorsque didSelectRowAtIndexPath est appelé car une ligne a été sélectionnée, la séquence est déclenchée avec la ligne de code ci-dessus. Ensuite, le générateur d'interface déclenche également la transition, car il est directement connecté à l'objet Cellule dans le générateur d'interface. Pour empêcher le constructeur d’interface de déclencher directement le segue. Vous devez connecter le segment depuis le haut du contrôleur de vue, sans imbriquer à l'intérieur de la cellule elle-même.

Donc, si vous rencontrez ce problème pour la même raison que moi, c’est-à-dire que vous appelez deux fois la même division, vous pouvez résoudre ce problème en dissociant DIRECTEMENT la connexion de la CELLULE avec la transition, haut de la hiérarchie des tableaux dans IB, plutôt que dans la cellule. Connectez le segment de votre View View Controller lui-même au segment. Si vous avez effectué cette opération correctement, lorsque vous sélectionnez la séquence, il convient de mettre en surbrillance la vue ENTIÈRE dont elle provient, et pas uniquement la cellule.

La documentation d'Apple se trouve maintenant sous PerformSegueWithIdentifier: Sender: Reference:

Normalement, les applications n'ont pas besoin de déclencher directement des divisions. Au lieu de cela, vous configurez un objet dans Interface Builder associé au contrôleur de vue, tel qu'un contrôle incorporé dans sa hiérarchie de vues, pour déclencher la séquence. Cependant, vous pouvez appeler cette méthode pour déclencher un segue par programmation, peut-être en réponse à une action qui ne peut pas être spécifiée dans le fichier de ressources du storyboard. Par exemple, vous pouvez l'appeler à partir d'un gestionnaire d'actions personnalisé utilisé pour traiter les événements d'agitation ou d'accéléromètre.

Dans mon cas, j'ai un bouton de recherche pour mon UITableView et il fallait déterminer si la séquence est appelée lorsque la table des résultats de la recherche est présente ou lorsque la vue de table normale est présente. Il me fallait donc déclencher directement la transition.

Supprimez donc le contrôle intégré du constructeur d’interface et collez-le simplement sur le contrôleur de vue lui-même, puis déclenchez la transition dans votre code!

Maintenant, plus de doubles-lieues! Et pas plus d'erreurs.

L’espoir que cela aide, m’a pris quelques bonnes heures pour aborder celui-ci.

93
user1927446

J'avais le même problème/message d'erreur que vous veniez tout à l'heure, je cherchais une solution et je me suis retrouvé à ce fil. Cependant, pour moi, j'ai constaté que la solution consiste en fait à n'avoir qu'une animation: mis animé: OUI seulement pour le Push final), espérons que cela aide

à votre santé.

11
code007

Je suis tombé sur le même problème qui résultait de la connexion d’un bouton d’une plume à deux actions différentes. Il a essayé de charger les deux contrôleurs de vue, corrompant ainsi la pile.

8
TigerCoding

Que voulez-vous dire quand vous dites que vous utilisez des méthodes init au lieu de méthodes viewDidLoad?

Si vous poussez un nouveau contrôleur de vue avant que l'ancien Push ait une chance d'être utilisé, vous obtiendrez ce genre d'erreur. Donc, mettre un certain code dans init et faire les choses prématurément pourrait certainement vous amener à l'erreur rapportée.

Au moment où init est exécuté sur un contrôleur de vue, la vue n'a pas encore été chargée!

4
occulus

J'ai eu ce problème et je suis nouveau sur la scène de développement iOS. Mais après avoir regardé mon inspecteur de connexions (avec le propriétaire du fichier) dans le constructeur d’interface, j’ai constaté que, comme j’avais copié un bouton, la méthode des boutons précédents lui était affectée, ainsi que la nouvelle méthode que j’avais créée. Je suppose que c’est de là que vient l’imbrication de mon problème, car il exécutait deux méthodes différentes qui donnaient toutes deux une vue sur le contrôleur de navigation. Je sais que la réponse à cette question a déjà été donnée, mais j’ai pensé que je la mettrais au cas où quelqu'un aurait une erreur aussi stupide que la mienne.

2
N1234

Couru dans le même problème. Dans mon cas, il me manquait une pause dans la déclaration de l'interrupteur, de sorte que deux ligues ont été tirées en même temps. Solution facile pour moi.

1
salilathalye

Cela a déjà été répondu, mais je pensais que cela pourrait aider les autres car j'ai la même erreur, mais sans utiliser les vues de table. J'ai finalement compris le problème. 

J'avais un bouton existant dont IBAction invoquait un pushViewController. J'ai créé un nouveau bouton en copiant le bouton existant. Le nouveau bouton comportait également une action qui appelait pushViewController. Lorsque le nouveau bouton a été tapé (retouche à l'intérieur) et que le contrôleur de vue a été poussé, j'ai eu cette erreur. J'ai supprimé le nouveau bouton, je l'ai créé de toutes pièces, je l'ai lié aux prises et actions existantes et l'erreur a disparu.

1
Vito Andolini

Récemment, j'ai rencontré le même problème. La raison était: -J'essayais de faire apparaître le contrôleur de vue deux fois par erreur. vous pouvez vérifier cette panne en définissant des points d'arrêt sur les contrôleurs Push et Pop View

1
Baljeet Singh

Mon problème était lié à l'activation du clavier.

Cela a été causé pour moi en poussant un ViewController à partir de la méthode déléguée de textField:

-(void)textFieldDidBeginEditing:(UITextField *)textField{

        FilterLocationViewController *destViewController = (FilterLocationViewController *)[self.storyboard instantiateViewControllerWithIdentifier:@"FilterLocationViewController"];

        [self.navigationController pushViewController:destViewController animated:YES];

}

En changeant le code à ceci:

-(void)textFieldDidBeginEditing:(UITextField *)textField{

        [_textFieldLocation resignFirstResponder]; //adding this line

        FilterLocationViewController *destViewController = (FilterLocationViewController *)[self.storyboard instantiateViewControllerWithIdentifier:@"FilterLocationViewController"];

        [self.navigationController pushViewController:destViewController animated:YES];

}

(en ajoutant la ligne [textField resignFirstResponder];), le problème a disparu. 

En gros, la leçon est qu'il ne faut pas modifier la pile de navigationController si le clavier est éteint. 

1
stackOverFlew

1) Vous pourriez peut-être essayer de passer les variables nécessaires en tant que propriétés avant d’appuyer sur UIViewController plutôt que d’utiliser les méthodes init avec des paramètres. De toute façon, vous aurez de toute façon besoin de ces paramètres au-delà de votre méthode init. 

De plus, dans votre méthode initWithCoordinates:, il vous manque les paramètres. Peut-être que vos méthodes init personnalisées sont une partie du problème. 

2) Juste parce que vous avez mentionné viewDidLoad - cette méthode est utilisée pour l’initialisation après le chargement d’une vue. Si vous créez UIViewController dans le code, comme il semble que vous le fassiez, vous devez utiliser loadView pour configurer vos sous-vues.

0
Mundi

Cela se passait pour moi à cause de ma UIControlEvents

    [button addTarget:self action:@selector(callSecondView) forControlEvents:UIControlEventAllTouchEvents];

Je devais changer le UIControlEventAllTouchEvents en UIControlEventTouchUpInside ou comme vous voulez que votre bouton fonctionne si vous aviez le problème à cause d'un appel UIButton.

0
John Riselvato

Je sais que cela a été répondu, mais cela pourrait aider les autres.

J'ai eu le même problème, mais c'était parce que j'utilisais un mauvais événement pour un bouton d'information . J'utilisais "UIControlEventAllTouchEvents" et cela a généré deux push de la même vue dans le contrôleur de navigation. L'événement correct était "UIControlEventTouchUpInside". Je suis nouveau sur iOS.

0
Carlos B

Ma solution était 

[self performSelector: @selector (moveTo) withObject: nil après retard: 0,5];

0
Ponja

Je ne sais pas pour les autres. Je pense que la plupart des utilisateurs de StoryBoard sont confrontés à un tel problème. J'utilise XIB. 

Dans mon cas, le problème était que, lorsque je passais à une autre vue en utilisant Push, .__, j'utilisais aussi 

 [self.navigationController popViewControllerAnimated:YES];

dans ViewWillDisappear de la vue actuelle au même moment. Il suffit de l'enlever et cela fonctionne bien.

J'utilisais POP, à cause de l'exigence et du flux . La hiérarchie était 1 -> 2 -> 3

J'étais sur la vue 2 et je voulais passer à la vue 3. Dans ce cas, j'ai rencontré cette erreur.

0
Jasmeet

J'ai également eu ce message d'erreur, et les transitions de la barre de navigation et du contrôleur de navigation étaient étranges. Ma configuration consistait en un ensemble de contrôleurs de navigation intégrés dans un contrôleur à barres d'onglets. Le problème était que je n’appelais pas super.viewDidLoad() dans l’implémentation de viewDidLoad du contrôleur de la barre de tabulation.

L'appel de super est quelque chose que les docs indiquent clairement que vous devriez faire lorsque vous surchargez viewDidLoad, et j'ai appris cela à la dure.

Peut-être que cela peut aider quelqu'un d'autre aussi!

0
empee

Dans mon cas, j'étais à la fois en train de régler la transition Push du storyboard et par programmation. Espérons que cela aidera n'importe qui

0
Kreutzer