12
votes

ViewDididappear a appelé deux fois sur le même exemple, mais seulement la première fois que cette classe charge forme la nib

J'ai un contrôleur de navigation. L'une des vues ajoute des sous-états personnalisés dans son ViewDidAppear: . Je remarque que la première fois que je navigue à une instance de ce contrôleur d'affichage après avoir lancé l'application, ViewDididappear: invoque deux fois. Si je fais partie de cette vue sur la pile et la navigue à nouveau, ViewDididAppear: n'applique qu'une seule fois par aspect. Toutes les apparences ultérieures 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-visions. Je travaille autour de ce problème en introduisant une variable de drapeau ou d'une sorte, mais j'aimerais comprendre ce qui se passe et comment se fait-il que je reçois deux invocations dans ces circonstances.


0 commentaires

8 Réponses :


1
votes

Peut-être que vous appelez ViewDidAppEar dans ViewDiDload (ou d'autres choses se passent là-bas), car elle n'est appelée qu'une seule fois lors du chargement de la vue de la mémoire. Cela correspondait, qu'il est invoqué deux fois seulement la première fois.


1 commentaires

C'était ma première pensée. Mais non, je ne fais pas ça. Et si je définis un point d'arrêt pour voir le ViewDididAppear: Invocation, aucune de mes propres méthodes ne l'apparaît.



0
votes

Vous devez définitivement fournir plus d'informations.

est-ce le contrôleur de vue root?
Peut-être que vous initiez le contrôleur de navigation avec ce contrôleur de vue racine, puis appuyez à nouveau sur le contrôleur de navigation?


2 commentaires

Idée intéressante, mais non, je ne le poussez pas deux fois. I NSLOG (@ "% @", [[auto NavigationController] ViewContrôleurs]); à partir de ViewDidAppear et voyez une instance de ma vue assis sur la vue Rain.


Peut-être que vous avez 2 contrôleurs de navigation par erreur?



18
votes

Vous ne devez jamais s'appuyer sur -ViewWillappear: / -ViewDidAppear: appelé de manière appropriée équilibrée avec les variantes disparues. Bien que les contrôleurs de vue du système feront de leur mieux, ils peuvent toujours faire fonctionner correctement les appels, je ne sais pas si elles le garantissent jamais, et certainement lors de l'utilisation de contrôleurs personnalisés, vous pouvez trouver des situations où elles peuvent être appelées plusieurs fois.

En bref, votre -ViewWillappear: -ViewDidAppear: Les méthodes doivent être idempotent, ce qui signifie si -ViewDidappear: est appelé deux fois dans un Rangez sur votre contrôleur, il devrait se comporter correctement. Si vous souhaitez charger des vues personnalisées, vous voudrez peut-être le faire dans -ViewDidLoad , puis mettez simplement l'écran à l'écran (si elles ne sont pas déjà) dans -ViewDidAppear: .

Vous pouvez également mettre un point d'arrêt dans votre -ViewDidAppappe: pour voir pourquoi il est appelé deux fois la première fois qu'il apparaît.


6 commentaires

J'ai un point d'arrêt dans ViewDididAppear: . Comment peut-il répondre à la question des ans?


Regardez la trace de la pile pour savoir pourquoi le système appelle cette méthode. Si la backtrage est différente pour les deux appels, vous pouvez l'utiliser pour essayer de déterminer ce qui se passe. Cela peut être utile ou peut ne pas être utile, selon précisément ce qui est contenu dans la backtrage.


Les piles ont l'air identiques, d'où ma surprise de votre suggestion. Ma solution consiste à refacturer le code afin que je puisse appeler le code dans ViewDidAppear: indirectement à partir de ViewDiDload: , et évitez ainsi tout le problème. J'accepte votre réponse même si la double invocation est toujours un mystère pour moi.


+1 pour utiliser le mot idempotent. Je n'ai pas encore corrigé mes appels dupliqués ViewDidAppear, mais j'ai appris un nouveau mot!


Est-il documenté qu'il pourrait ne pas être équilibré?


@TCurdt: Je ne le pense pas, mais surtout, il n'y a pas de documentation en disant qu'ils sont garantis pour être équilibrés. Et une VC troisième partie mal écrite peut assez facilement les laisser déséquilibré.



0
votes

Une autre solution qui a peut-être été votre cause sous-jacente: assurez-vous de ne présenter aucun nouveau contrôleur d'affichage de votre ViewWillappear: code> Méthode.

J'appelle: P>

[appDel.window.rootViewController presentViewController:login animated:YES completion:nil];


0 commentaires

1
votes

Ce n'était pas un bogue IOS 5, mais un comportement caché de AddChildViewController :. Je devrais déposer un radar faute de documentation, je pense https://github.com/defagos/coconutkit/issues/4


0 commentaires

0
votes

C'est un problème aussi ennuyeux, vous penseriez qu'il fonctionne une fois, mais j'en ai maintenant découvert à ce sujet qui causant que mayhem ... cela s'applique aux 3 (viewDididAppEar, ViewDidLoad et ViewWillappappear), je reçois cela quand intégrer avec un terminal de paiement; Une fois que cela a fini d'appeler l'API, la fenêtre est rechargée lorsqu'elle est déjà à l'écran et que tout ce que la mémoire est toujours là (non conservé).

Je l'ai résolu en procédant à toutes les routines mentionnées ci-dessus, ci-dessous est un échantillon de l'un d'entre eux: xxx

répéter ci-dessus pour tous les deux autres, Cela l'empêche de courir deux fois. Cela n'a jamais eu lieu avant que Steve Jobs est mort !!!

Cordialement Cordialement Heider Sati


0 commentaires

1
votes

Si vous avez une ligne comme celle-ci dans votre Appdelegate xxx

Assurez-vous de ne pas avoir de propriété "nom de base du fichier de nib principal" dans votre plis définir sur "window.xib" ou quelle que soit votre fenêtre de fenêtre personnalisée nommée. Si vous le faites, supprimez cette ligne de votre plis et assurez-vous de vous aussi comme xxx

dans votre appdelegate après instanciation de votre fenêtre. Dans la plupart des cas, vous pouvez ensuite supprimer en toute sécurité la fenêtre.xib aussi.


0 commentaires

-1
votes

Ajout [super viewDidAppear: animé]; code> a travaillé pour moi:

//Called twice
- (void)viewDidAppear:(BOOL)animated{

}

//Called once
- (void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
}


3 commentaires

En enregistrant cela, le Super ne cesse pas de charger deux fois.


Ce travail pour moi. J'ai eu un code comme celui-ci: Super.viewwillappear (True), après avoir changé pour: Super.ViewWillappear (animé) Il a commencé à fonctionner correctement.


Tous les bownvotes, s'il vous plaît bowvote avec commentaire valide. Afin que je puisse améliorer la réponse.