web-dev-qa-db-fra.com

Essayez de présenter * sur * dont la vue n'est pas dans la hiérarchie des fenêtres

J'essaie de créer un contrôleur de vue modale dans mon délégué d'application (j'ai créé une fonction appelée showLoginView). Mais chaque fois que j'essaie de l'appeler, un avertissement s'affiche dans XCode:

Warning: Attempt to present <PSLoginViewController: 0x1fda2b40> on <PSViewController: 0x1fda0720> whose view is not in the window hierarchy!

Voici le code de la méthode:

- (void)showLoginView
{
    PSLoginViewController *loginViewController = [[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:NULL] instantiateViewControllerWithIdentifier:@"PSLoginViewController"];
    [self.window.rootViewController presentViewController:loginViewController animated:NO completion:nil];
}

Comment puis-je ajouter la vue à la hiérarchie des fenêtres? Ou peut-être que je fais quelque chose de très faux?

36
patryk

Vous ne pouvez pas afficher un contrôleur de vue modale à partir de appDelegate. Vous devez afficher un ViewController modal dans le viewController actuellement affiché en plein écran. En d'autres termes, vous devez insérer ce code dans votre contrôleur de vue racine ou dans celui par lequel vous souhaitez afficher le vC modal depuis ...

En outre, vous voudrez utiliser la méthode "presentModalViewController" pour présenter le modal. Vous pouvez définir des propriétés sur le vc modal telles que:

vC.modalPresentationStyle = UIModalPresentationFormSheet;
vC.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:vC animated:YES];
30
HackyStack

Vous pouvez réellement présenter un contrôleur de vue modale à partir de AppDelegate tant que vous détectez le viewController visible actuel et que vous vous occupez du cas où votre contrôleur actuel est un navigationController.

Voici ce que je fais:

UIViewController *activeController = [UIApplication sharedApplication].keyWindow.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]]) {
   activeController = [(UINavigationController*) activeController visibleViewController];
}
[activeController presentModalViewController:loginViewController animated:YES];
21
Erwan
UIViewController *activeController = [UIApplication sharedApplication].keyWindow.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]])
{
   activeController = [(UINavigationController*) activeController visibleViewController];
}
else if (activeController.modalViewController)
{
    activeController = activeController.modalViewController;
}
[activeController presentModalViewController:vc animated:YES];
8
SFeng

J'ai rencontré ce problème sur iOS 7 - la solution pour que l'une des solutions proposées fonctionne est d'appeler 

[self.window makeKeyAndVisible];

dans votre AppDelegate. Après cet appel, présenter une vue modale à partir de la fenêtre rootViewController fonctionnait.

7
David Ganster

Une autre raison de cet avertissement peut être que vous souhaitez présenter un contrôleur de vue à partir d'une instance qui n'est pas le contrôleur de vue le plus haut.

Donc, vous devez d’abord obtenir le meilleur UIViewController et utiliser cette instance pour appeler presentViewController:

UIViewController *root = [UIApplication sharedApplication].keyWindow.rootViewController;
while (root.presentedViewController) {
    root = root.presentedViewController;
}
6
Titus T

Vous pouvez NSLog (@ "% @", self.window.rootViewController) et voir ce qu'est réellement le rootViewController.

Je suis entré dans ce problème, quand le rootViewController est un UIViewController normal . Le remplacer par un UINavigationController, je souhaite que cela aide.

3
Sanbrother

A fait face à ce problème en essayant de présenter le contrôleur à partir de l'appel du délégué d'un autre contrôleur. c'est-à-dire: afficher le filtre de recherche avec le délégué, une fois que cela est fait sur mon contrôleur et recevoir les données via le délégué puis le contrôleur actuel, tout ce que j'avais à faire est d'envoyer présentons sur votre vue depuis le thread principal un autre contrôleur de cet autre thread, il faut donc revenir au thread principal, il suffit de mettre le code de présentation comme ceci: 

     dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:searchVC animated:true completion:nil];
 });

J'espère que cela t'aides !

0
IsPha