En enquêtant sur une fuite de mémoire, j'ai découvert un problème lié à la technique d'appel setRootViewController:
à l' intérieur d'un bloc d'animation de transition:
[UIView transitionWithView:self.window
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{ self.window.rootViewController = newController; }
completion:nil];
Si l'ancien contrôleur de vue (celui en cours de remplacement) présente actuellement un autre contrôleur de vue, le code ci-dessus ne supprime pas la vue présentée de la hiérarchie de vues.
Autrement dit, cette séquence d'opérations ...
- X devient le contrôleur de vue racine
- X présente Y, de sorte que la vue de Y soit à l'écran
- Utilisation
transitionWithView:
pour faire de Z le nouveau contrôleur de vue racine
... semble OK pour l'utilisateur, mais l'outil Hiérarchie des vues de débogage révélera que la vue de Y est toujours là derrière la vue de Z, à l'intérieur d'un UITransitionView
. Autrement dit, après les trois étapes ci-dessus, la hiérarchie des vues est:
- UIWindow
- UITransitionView
- UIView (vue de Y)
- UIView (vue de Z)
- UITransitionView
Je soupçonne que c'est un problème car, au moment de la transition, la vue de X ne fait pas partie de la hiérarchie des vues.
Si j'envoie dismissViewControllerAnimated:NO
à X immédiatement avant transitionWithView:
, la hiérarchie de vue résultante est:
- UIWindow
- UIView (vue de X)
- UIView (vue de Z)
Si j'envoie dismissViewControllerAnimated:
(OUI ou NON) à X, puis que j'effectue la transition dans le completion:
bloc, la hiérarchie de la vue est correcte. Malheureusement, cela interfère avec l'animation. Si vous animez le licenciement, cela fait perdre du temps; sinon animée, elle a l'air cassée.
J'essaie d'autres approches (par exemple, créer une nouvelle classe de contrôleur de vue de conteneur pour servir de contrôleur de vue racine) mais je n'ai rien trouvé qui fonctionne. Je mettrai à jour cette question au fur et à mesure.
Le but ultime est de passer directement de la vue présentée à un nouveau contrôleur de vue racine, et sans laisser de hiérarchies de vues parasites.
UIWindow
est la chose à faire, mais je n'ai pas eu le temps d'expérimenter beaucoup.Réponses:
J'ai eu un problème similaire récemment. J'ai dû supprimer manuellement cela
UITransitionView
de la fenêtre pour résoudre le problème, puis appeler la fonction de rejet sur le contrôleur de vue racine précédent pour garantir sa désallocation.Le correctif n'est pas vraiment très sympa mais à moins que vous n'ayez trouvé un meilleur moyen depuis la publication de la question, c'est la seule chose que j'ai trouvée pour fonctionner!
viewController
est juste lenewController
de votre question initiale.J'espère que cela vous aidera aussi à résoudre votre problème, c'est une douleur absolue dans le cul!
(Voir l'historique des modifications pour les autres versions de Swift)
Pour une implémentation plus agréable en tant qu'extension
UIWindow
permettant de passer une transition facultative.Usage:
Ou
la source
UITransitionView
dans votre application, car elle est alors sélectionnée dans le cadre des symboles de l'application que je pense que l'App Store utilise pour vérifier.J'ai fait face à ce problème et cela m'a ennuyé pendant une journée entière. J'ai essayé la solution obj-c de @ Rich et il s'avère que lorsque je veux présenter un autre viewController après cela, je serai bloqué avec un UITransitionView vide.
Enfin, j'ai compris de cette façon et cela a fonctionné pour moi.
Très bien, maintenant tout ce que vous avez à faire est d'appeler
[self setRootViewController:newViewController];
lorsque vous voulez changer de contrôleur de vue racine.la source
dismissViewControllerAnimated:
regards peut-être un peu mieux que pas d'animation. Evite cependant les fantômesUITransitionView
dans la hiérarchie des vues.J'essaie une chose simple qui fonctionne pour moi sur iOs 9.3: il suffit de supprimer l'ancienne vue viewController de sa hiérarchie lors de la
dismissViewControllerAnimated
finalisation.Travaillons sur les vues X, Y et Z comme expliqué par benzado :
Qui donnent :
Dans mon cas, X et Y sont bien dealloc et leur point de vue n'est plus dans la hiérarchie!
la source
Eu un problème similaire. Dans mon cas, j'avais une hiérarchie viewController, et l'un des contrôleurs de vue enfants avait un contrôleur de vue présenté. Lorsque j'ai changé le contrôleur de vue racine de Windows, pour une raison quelconque, le contrôleur de vue présenté était toujours dans la mémoire. Donc, la solution était de rejeter tous les contrôleurs de vue avant de changer le contrôleur de vue racine de Windows.
la source
Je suis arrivé à ce problème en utilisant ce code:
La désactivation de ce code a résolu le problème. J'ai réussi à faire fonctionner cela en n'activant cette animation de transition que lorsque la barre de filtre qui s'anime est initialisée.
Ce n'est pas vraiment la réponse que vous recherchez, mais cela pourrait vous amener sur le bon pad pour trouver votre solution.
la source