web-dev-qa-db-fra.com

Avertissement: il est déconseillé de présenter les contrôleurs de vue sur des contrôleurs de vue détachés

Dans mon application, j'utilise un contrôleur de navigation. Plus tard, dans certains cas, j'utilise presentViewController pour afficher une image zoomée . 

Je reçois cette erreur dans iOS 7 uniquement. Cela fonctionne très bien sous iOS 6 et les versions antérieures:

Présenter des contrôleurs de vue sur des contrôleurs de vue détachés est découragé

162
Gagan Joshi

Une des solutions à cela est si vous avez childviewcontroller. Il vous suffit donc de presentviewcontroller sur son parent en lui donnant 

[self.parentViewController presentViewController:viewController animated:YES completion:nil];

Et pour les licenciements, utilisez le même contrôleur.

[self dismissViewControllerAnimated:YES completion:nil];

C'est la solution parfaite qui fonctionne pour moi.

8
Gagan Joshi

Pour éviter l’avertissement dans une navigation Push, vous pouvez directement utiliser:

[self.view.window.rootViewController presentViewController:viewController animated:YES completion:nil];

Et ensuite, dans votre contrôleur de vue modale, lorsque tout est terminé, vous pouvez simplement appeler: 

[self dismissViewControllerAnimated:YES completion:nil];

197
cdescours

La raison de cet avertissement est que je présentais un contrôleur de vue sur une petite vue qui n’est pas en pleine taille. Ci-dessous est l'image de mon projet. où sur cliquez sur quatre option ci-dessus. L'utilisateur accède à la vue différente de childviewcontroller (cela fonctionne comme tabViewcontroller). Mais le contrôle de vue enfant contient une vue de petite taille. Donc, si nous présentons une vue de childviewcontroller, cet avertissement s’affiche. 

master detail view

Et pour éviter cela, vous pouvez présenter une vue sur le parent de childviewcontroller

  [self.parentViewController presentViewController:viewController animated:YES completion:nil];
59
Gagan Joshi

Attendez viewDidAppear():

Cette erreur peut également survenir si vous essayez de présenter le contrôleur de vue avant que la vue apparaisse réellement, par exemple en présentant la vue dans viewWillAppear() ou une version antérieure . Essayez de présenter une autre vue après viewDidAppear() ou à l'intérieur de celle-ci.

45
Azaxis

Dans mon cas, une vue sampleViewController a été ajoutée en tant que sous-vue, puis une présentation de survol à partir de la vue de sampleViewController (ici self à la place d'une instance UIViewController):

[self.view addSubview:sampleViewController.view];

La bonne façon devrait être ci-dessous:

// make sure the vc has been added as a child view controller as well
[self addChildViewController:sampleViewController];
[self.view addSubview:sampleViewController.view];
[sampleViewController didMoveToParentViewController:self];

B.t.w., cela fonctionne également pour le cas qui présente un popover de la forme d'une cellule tableview, il vous suffit de vous assurer que le contrôleur tableview a également été ajouté en tant que contrôleur de vue enfant.

18
Kjuly

Je pense que le problème est que vous n’avez pas une hiérarchie appropriée du contrôleur de vue. Définissez le rootviewcontroller de l'application, puis affichez les nouvelles vues en poussant ou en présentant de nouveaux contrôleurs de vue dessus. Laissez chaque contrôleur de vue gérer leurs vues. Seuls les contrôleurs de vue de conteneur, tels que tabbarviewcontroller, doivent jamais ajouter d'autres vues de contrôleur de vue à leurs propres vues. Lisez le guide de programmation des contrôleurs de vue pour en savoir plus sur l'utilisation correcte des contrôleurs de vue. https://developer.Apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/

16
Daniel Ytterbrink

J'ai presque le même problème. La raison en était que j'ai essayé de présenter "un" contrôleur sur un autre et qu'après l'animation, j'ai paramétré le contrôleur présenté en tant que root. Après cette opération, tous les autres contrôleurs présents m'amènent à l'avertissement suivant: " La présentation des contrôleurs de vue sur des contrôleurs de vue détachés est déconseillée ". Et je résous cet avertissement en réglant simplement "certains" contrôleurs en tant que root sans aucune présentation au début.

Enlevé:

[[self rootController] presentViewController:controller animated:YES completion:^{

       [self window].rootViewController = controller;

       [[self window] makeKeyAndVisible];}];

Il suffit de faire en tant que root sans aucune présentation:

 [[self window] setRootViewController:controller];
9
averem

Swift 3

Pour ceux qui tombent sur cela, voici la réponse rapide.

self.parent?.present(viewController, animated: true, completion: nil)
7
Jeremie

Utilisez [self.navigationController presentViewController:xxx animated:YES completion:nil] dans iOS 8.

6
Tao Fang

Essayez ce code

UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:<your ViewController object>];

[self.view.window.rootViewController presentViewController:navigationController animated:YES completion:nil];
5
Vlad

Oui, j'ai également été confronté au même message d'avertissement lors de l'affichage d'un contrôleur Alert qui se trouvait dans une autre vue. Plus tard, j'ai évité cela en présentant le contrôleur d'alerte à partir du contrôleur de vue parent comme ci-dessous:

[self.parentViewController presentViewController:alertController animated:YES completion:nil];
3

vous devez ajouter le contrôleur de vue qui présentera le nouveau contrôleur en tant qu'enfant du contrôleur de vue parent.

Supposons que vous ayez yourMainViewController, puis que vous ajoutiez un nouveau contrôleur appelé controllerA et que vous souhaitiez présenter un nouveau contrôleur appelé controllerB de controllerA

vous devez écrire quelque chose comme ceci:

[self addChildViewController:controllerA]; //self is yourMainViewController
[self.view addsubView:controllerA.view]; 

et dans controllerA, vous pouvez présenter le nouveau contrôleur sans avertissements

[self presentViewController:controllerB animated:YES completion:nil]; //self is controllerA
3
Chuy47

Essayez de présenter sur TabBarController s'il s'agit d'une application basée sur TabBarController

[self.tabBarController presentViewController:viewController animated:YES completion:nil];

La raison pourrait être self est l'enfant de TabBarController et vous essayez de présenter à partir d'une ChildViewController.

2
Warif Akhand Rishi

Assurez-vous que vous avez un contrôleur de vue racine pour commencer. Vous pouvez le définir dans didFinishLaunchingWithOptions.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    [window setRootViewController:viewController];
}
1
samwize

Beaucoup de raisons pour cet avertissement. Le mien est parce que j'ai une séquence connectée d'un ViewController à un autre qui sera présentée modalement Cependant, le ViewController que je présente est généré dynamiquement par un PageViewController. C'est pourquoi il est détaché dans le Storyboard. Mon application ne va pas se bloquer à cause de cela; mais je voudrais faire taire l'avertissement.

1
Lee Probert

J'ai atteint sur ce fil où j'ai une barre de navigation personnalisée et j'appelais un AlertViewController à travers elle.

Je devais l'ajouter en tant qu'enfant à mon contrôleur de vue principal. Ensuite, je pourrais appeler le présenter sans aucun avertissement.

Vous devez ajouter votre Zoomed Image View Controller en tant qu'enfant du ViewController principal.

(par exemple)

[self addChildViewController:ZoomedImageViewController];

Ensuite, vous pourrez appeler votre ZoomedImageViewController

[self presentViewController:ZoomedImageViewController];
0
Naveed Abbas

Dans Swift 4.1 et Xcode 9.4.1

La solution est 

DispatchQueue.main.async(execute: {
    self.present(alert, animated: true)
})

Si j'écris comme ça, je reçois la même erreur

let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: { action in
    })
alert.addAction(defaultAction)

present(alert, animated: true, completion: nil) 

Je reçois la même erreur

Presenting view controllers on detached view controllers is discouraged <MyAppName.ViewController: 0x7fa95560Z070>.

La solution complète est 

let alert = UIAlertController(title: "title", message: "message", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: { action in
     })
alert.addAction(defaultAction)
//Made Changes here    
DispatchQueue.main.async(execute: {
    self.present(alert, animated: true)
})
0
iOS

Cela dépend si vous souhaitez afficher votre alerte ou quelque chose de similaire dans n'importe quel type de UIViewController.

Vous pouvez utiliser cet exemple de code:

UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Alert" message:@"Example" preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:nil];

[alert addAction:cancelAction];


[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:alert animated:true completion:nil];
0
Fabio