J'ai un contrôleur de navigation. L'une des vues ajoute des sous-vues personnalisées dans son viewDidAppear:
. Je remarque que la première fois que je navigue vers une instance de ce contrôleur de vue après le lancement de l'application, viewDidAppear:
invoque deux fois. Si j'ouvre cette vue de la pile et y retourne, viewDidAppear:
invoque seulement une fois par apparence. Toutes les apparences suivantes invoquent viewDidAppear:
une fois. Le problème pour moi est que la première fois que j'arrive à cette vue, je me retrouve avec deux fois le nombre de sous-vues. Je contourne ce problème en introduisant une variable de drapeau ou un tel, mais j'aimerais comprendre ce qui se passe et comment se fait-il que j'obtienne deux invocations dans ces circonstances.viewDidAppear appelé deux fois sur la même instance, mais seulement la première fois que cette classe charge le formulaire NIB
Répondre
Vous ne devez jamais compter sur -viewWillAppear:
/-viewDidAppear:
étant appelé de manière appropriée équilibrée avec les variantes disparaissent. Bien que les contrôleurs de vue du système fassent de leur mieux pour bien encadrer les appels correctement, je ne sais pas s'ils les garantissent, et certainement lorsque vous utilisez des contrôleurs de vue personnalisés, vous pouvez trouver des situations où ils peuvent être appelés plusieurs fois. En résumé, vos méthodes -viewWillAppear:
/-viewDidAppear:
doivent être idempotentes, ce qui signifie que si -viewDidAppear:
est appelé deux fois de suite sur votre contrôleur, il doit se comporter correctement. Si vous souhaitez charger des vues personnalisées, vous pouvez le faire dans -viewDidLoad
à la place et ensuite simplement mettre l'écran (si ce n'est déjà fait) dans -viewDidAppear:
.
Vous pouvez également mettre un point d'arrêt dans votre méthode -viewDidAppear:
pour voir pourquoi il est appelé deux fois la première fois qu'il apparaît.
peut-être vous appelez viewDidAppear
dans viewDidLoad
(ou d'autres choses se passe là-bas), car il est appelé une seule fois lors du chargement de la vue de la mémoire. Il correspondrait, qu'il est invoqué deux fois seulement la première fois.
Ce fut ma première pensée. Mais non, je ne fais pas ça. Et si je mets un point d'arrêt pour voir l'invocation de 'viewDidAppear:', aucune de mes méthodes n'apparaît dedans. – iter
Vous devriez certainement fournir plus d'informations.
Est-ce le contrôleur de vue racine?
Peut-être que vous initiez le contrôleur de navigation avec ce contrôleur de vue racine, puis le repoussez sur le contrôleur de navigation?
Idée intéressante, mais non, je ne la pousse pas deux fois. Je 'NSLog (@"% @ ", [[self navigationController] viewControllers]);' from 'viewDidAppear' et voir une instance de ma vue en haut de la vue racine. – iter
Peut-être avez-vous deux contrôleurs de navigation par erreur? –
Une autre solution qui peut avoir été votre cause sous-jacente: Assurez-vous de ne pas présenter de nouveaux contrôleurs de vue à partir de votre méthode viewWillAppear:
.
j'appelle:
[appDel.window.rootViewController presentViewController:login animated:YES completion:nil];
à l'intérieur viewWillAppear
et de voir mon origine méthode VC viewDidAppear:
appelé deux fois successivement avec la même trace de la pile que vous mentionnez.Et aucun appel intermédiaire à viewDidDisappear:
Moving presentViewController:
à ORIGINAIRE méthode VC viewDidAppear:
éclairci la question de la double appel, et maintenant le flux est:
- originale
viewDidAppear:
appelé- Appel
presentViewController
ici
- Appel
- Original
viewDidDisappear:
appelé - Nouvelle vue est présentée et ne me donne un avertissement sur
"unbalanced VC display"
fixe avec l'aide de cette réponse: https://stackoverflow.com/a/13315360/1143123 tout en essayant de résoudre "Unbalanced calls to begin/end appearance transitions for ..."
Ce ne fut pas un bug iOS 5, mais un comportement caché de addChildViewController :. Je devrais classer un radar par manque de documentation, je pense https://github.com/defagos/CoconutKit/issues/4
c'est un problème ennuyeux, on pourrait penser qu'il fonctionne une fois mais alors je découvre maintenant à propos de ce qui cause le chaos ... Cela s'applique à tous 3 (ViewDidAppear, ViewDidLoad et ViewWillAppear), je reçois ceci lors de l'intégration avec un terminal de paiement; Une fois l'API terminée, la fenêtre est en train d'être rechargée quand elle est déjà à l'écran et toute sa mémoire est toujours là (non conservée).
Je résolus en procédant comme suit à toutes les routines mentionnées ci-dessus, au-dessous est un échantillon à l'un d'entre eux:
BOOL viewDidLoadProcessed = false;
-(void)viewDidLoad:(BOOL)animated
{
if (!viewDidLoadProcessed)
{
viewDidLoadProcessed = YES;
.
.
.
... do stuff here...
.
.
}
}
Répétez ce qui précède pour tous les deux autres, ce qu'il empêche de courir deux fois. Cela ne s'est jamais produit avant que Steve Jobs ne meure !!!
Cordialement Heider Sati
Si vous avez une ligne comme celui-ci dans votre AppDelegate
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
assurez-vous que vous ne possédez pas une propriété « nom de base de fichier nib principal » dans votre plist défini sur "Window.xib" ou quel que soit le nom de votre plume de fenêtre personnalisée. Si vous le faites, retirez cette ligne de votre plist et assurez-vous quelque chose comme
yourRootVC = [[UIViewController alloc] init];
[window setRootViewController:yourRootVC];
dans votre AppDelegate après instanciation votre fenêtre. Dans la plupart des cas, vous pouvez également supprimer le fichier Window.xib en toute sécurité.
Ajout [super viewDidAppear:animated];
a fonctionné pour moi:
//Called twice
- (void)viewDidAppear:(BOOL)animated{
}
//Called once
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
}
En enregistrant cela, le super n'arrête pas de charger deux fois. –
- 1. viewDidAppear appelé deux fois, mais viewWillAppear a appelé une fois
- 2. viewDidLoad est appelé seulement la première fois
- 3. dojo.parser.parse ne fonctionne que la première fois il est appelé
- 4. viewDidAppear: appelé deux fois sur le contrôleur de vue modale présenté au démarrage
- 5. Outlook Addin seulement le chargement sur la première instance d'Outlook
- 6. UIWebView shouldStartLoadWithRequest seulement appelé une fois?
- 7. Le service Android démarre/lie correctement, mais seulement la première fois
- 8. JPA persiste deux fois la même entité
- 9. Garbled texte en utilisant FETStationPanels, mais seulement la première fois que ça s'appelle
- 10. NSKeyedArchiver étant appelé deux fois
- 11. Servlet étant appelé deux fois!
- 12. La première fois que l'application adhoc est chargée sur l'iPhone
- 13. Réaction OnPropertyChanged différente la première fois et la deuxième fois
- 14. InnerHtml fonctionne la première fois, mais pas après la publication
- 15. iPhone chargement vue de nib fonctionne seulement une fois
- 16. NSMutableURLRequest: didReceiveData n'a pas été appelé pour la première fois
- 17. Pourquoi est-ce que je peux changer le registre seulement la première fois?
- 18. Rails variable charge la première fois, puis est nul!
- 19. en ajoutant deux fois le même objet
- 20. joindre la même table deux fois sur des colonnes différentes
- 21. UITableView méthode déléguée appelé deux fois
- 22. Témoin pour la première fois
- 23. WCF méthode ReliableMessaging appelé deux fois
- 24. Comment prendre en charge à la fois DataContractSerializer et XMLSerializer pour le même contrat sur le même hôte?
- 25. OnEditorActionListener appelé deux fois avec le même événementTime sur le clavier SenseUI
- 26. Pourquoi le destructeur de la classe est-il appelé deux fois?
- 27. Javascripts exécuter correctement qu'après la première fois la page se charge dans Google Chrome 4
- 28. WPF: Comment GARDER la même instance ItemTemplate une fois créée?
- 29. Est-ce que viewDidAppear: méthode animée peut être appelée plusieurs fois pour un seul presentModalViewController: animé?
- 30. sqlite3 fonctionne INSERT et UPDATE requêtes fines première fois, mais la deuxième fois renvoie l'erreur
J'ai un point d'arrêt dans 'viewDidAppear:'. Comment peut-il répondre à la question pourquoi? – iter
Examinez la trace de la pile pour savoir pourquoi le système appelle cette méthode. Si le backtrace est différent pour les deux appels, vous pouvez l'utiliser pour essayer de comprendre ce qui se passe. Cela peut ou peut ne pas être utile, en fonction précisément de ce qui est contenu dans le backtrace. –
Les piles semblent identiques, d'où ma surprise à votre suggestion. Ma solution est de refactoriser le code afin que je puisse appeler le code dans 'viewDidAppear:' indirectement à partir de 'viewDidLoad:', et éviter ainsi tout le problème. J'accepte votre réponse même si la double invocation est toujours un mystère pour moi. – iter