Question Essayer de présenter UIViewController sur UIViewController dont la vue n'est pas dans la hiérarchie de la fenêtre


J'ai commencé à utiliser Xcode 4.5 et j'ai eu cette erreur dans la console:

Attention: essayez de présenter <finishViewController: 0x1e56e0a0> sur <ViewController: 0x1ec3e000> dont la vue n'est pas dans la hiérarchie de la fenêtre!

La vue est toujours présentée et tout dans l'application fonctionne bien. Est-ce quelque chose de nouveau dans iOS 6?

C'est le code que j'utilise pour changer entre les vues:

UIStoryboard *storyboard = self.storyboard;
finishViewController *finished = 
[storyboard instantiateViewControllerWithIdentifier:@"finishViewController"];

[self presentViewController:finished animated:NO completion:NULL];

486
2017-08-08 10:47


origine


Réponses:


D'où appelez-vous cette méthode? J'ai eu un problème où je tentais de présenter un contrôleur de vue modal dans le viewDidLoad méthode. La solution pour moi était de déplacer cet appel à la viewDidAppear: méthode.

Ma présomption est que la vue du contrôleur de vue n'est pas dans la hiérarchie des vues de la fenêtre au moment où elle a été chargée (lorsque la viewDidLoad message est envoyé), mais est dans la hiérarchie de fenêtre après sa présentation (lorsque le viewDidAppear: le message est envoyé).


Mise en garde

Si vous appelez presentViewController:animated:completion: dans le viewDidAppear: vous pouvez rencontrer un problème dans lequel le contrôleur de vue modal est toujours présenté chaque fois que la vue du contrôleur de vue apparaît (ce qui est logique!) et que le contrôleur de vue modal présenté ne disparaîtra jamais ...

Peut-être ce n'est pas le meilleur endroit pour présenter le contrôleur de vue modal, ou peut-être un état supplémentaire doit être conservé qui permet au contrôleur de vue présentateur de décider s'il doit ou non présenter immédiatement le contrôleur de vue modal.


1051
2017-09-07 14:36



Une autre cause potentielle:

J'ai eu ce problème quand je présentais accidentellement le même contrôleur de vue deux fois. (Une fois avec performSegueWithIdentifer:sender: qui a été appelé lorsque le bouton a été appuyé, et une deuxième fois avec un segue connecté directement au bouton).

Effectivement, deux pages tiraient en même temps, et j'ai eu l'erreur: Attempt to present X on Y whose view is not in the window hierarchy!


52
2018-04-17 19:56



viewWillLayoutSubviews et viewDidLayoutSubviews (iOS 5.0+) peut être utilisé à cette fin. Ils sont appelés plus tôt que viewDidAppear.


33
2018-02-22 03:10



J'ai également rencontré ce problème lorsque j'ai essayé de présenter un contrôleur de vue dans viewDidLoad. J'ai essayé la réponse de James Bedford. Cela fonctionne, mais mon application affiche d'abord l'arrière-plan pendant 1 ou 2 secondes.

Après la recherche, je trouve enfin une autre façon de résoudre ce problème est d'utiliser le contrôleur de vue enfant.

- (void)viewDidLoad
{
    ...
    [self.view addSubview:navigationViewController.view];
    [self addChildViewController:navigationViewController];
    ...
}

16
2017-12-06 05:35



Pour afficher n'importe quelle sous-vue de la vue principale, veuillez utiliser le code suivant

UIViewController *yourCurrentViewController = [UIApplication sharedApplication].keyWindow.rootViewController;

while (yourCurrentViewController.presentedViewController) 
{
   yourCurrentViewController = yourCurrentViewController.presentedViewController;
}

[yourCurrentViewController presentViewController:composeViewController animated:YES completion:nil];

Pour rejeter une sous-vue de la vue principale, veuillez utiliser le code suivant

UIViewController *yourCurrentViewController = [UIApplication sharedApplication].keyWindow.rootViewController;

while (yourCurrentViewController.presentedViewController) 
{
   yourCurrentViewController = yourCurrentViewController.presentedViewController;
}

[yourCurrentViewController dismissViewControllerAnimated:YES completion:nil];

16
2018-03-09 06:22



Probablement, comme moi, vous avez une mauvaise racine viewController

Je veux afficher un ViewController dans un non-UIViewController le contexte,

Donc je ne peux pas utiliser un tel code:

[self presentViewController:]

Donc, j'ai un UIViewController:

[[[[UIApplication sharedApplication] delegate] window] rootViewController]

Pour une raison quelconque (bug logique), le rootViewController est autre chose que prévu (une normale UIViewController). Puis je corrige le bug en remplaçant rootViewController avec un UINavigationController, et le problème est parti.


11
2017-07-24 02:30



Mon problème était que je jouais le segue dans UIApplicationDelegatede didFinishLaunchingWithOptions méthode avant d'appeler makeKeyAndVisible() sur la fenêtre.


5
2018-05-17 01:59



TL; DR Vous ne pouvez avoir qu'un seul rootViewController et c'est le dernier présenté. Donc, n'essayez pas de demander à un viewcontroller de présenter un autre viewcontroller lorsqu'il en a déjà présenté un qui n'a pas été rejeté.

Après avoir fait mes propres tests, je suis arrivé à une conclusion.

Si vous avez un rootViewController que vous voulez tout présenter, vous pouvez rencontrer ce problème.

Voici mon code rootController (open est mon raccourci pour présenter un viewcontroller depuis la racine).

func open(controller:UIViewController)
{
    if (Context.ROOTWINDOW.rootViewController == nil)
    {
        Context.ROOTWINDOW.rootViewController = ROOT_VIEW_CONTROLLER
        Context.ROOTWINDOW.makeKeyAndVisible()
    }

    ROOT_VIEW_CONTROLLER.presentViewController(controller, animated: true, completion: {})
}

Si j'appelle ouvert deux fois de suite (indépendamment du temps écoulé), cela fonctionnera très bien sur le premier ouvert, mais PAS sur le second ouvert. La deuxième tentative ouverte entraînera l'erreur ci-dessus.

Toutefois, si je ferme la vue la plus récemment présentée, appelez open, cela fonctionne très bien lorsque j'appelle open (sur un autre viewcontroller).

func close(controller:UIViewController)
{
    ROOT_VIEW_CONTROLLER.dismissViewControllerAnimated(true, completion: nil)
}

Ce que j'ai conclu, c'est que le composant rootViewController de MALL-RECENT-CALL est sur la hiérarchie de la vue (même si vous ne l'avez pas ignoré ou supprimé). J'ai essayé de jouer avec tous les appels du loader (viewDidLoad, viewDidAppear, et faire des appels de dispatch retardés) et j'ai trouvé que la seule manière que je pourrais l'obtenir fonctionne UNIQUEMENT appelant présent du contrôleur de vue le plus supérieur.


4
2017-08-17 19:48



Si vous avez un objet AVPlayer avec une vidéo lue, vous devez d'abord mettre la vidéo en pause.


3
2018-06-18 20:11