web-dev-qa-db-fra.com

Rejeter un contrôleur de vue présentée

J'ai une question théorique. Maintenant, je lis le ViewController guide d’Apple.

Ils ont écrit: 

Lorsque vient le temps de rejeter un contrôleur de vue présenté, le fichier L’approche privilégiée consiste à laisser le contrôleur de la vue présentation congédier il. En d’autres termes, dans la mesure du possible, le même contrôleur de vue que présenté, le contrôleur de la vue devrait également assumer la responsabilité de le rejetant. Bien qu'il existe plusieurs techniques pour notifier le présentation contrôleur de vue que son contrôleur de vue présenté devrait être rejetée, la technique privilégiée est la délégation.

Mais je ne peux pas expliquer pourquoi je dois créer un protocole dans VC présenté et ajouter délégable varible, créer une méthode de délégué dans la présentation de VC pour rejeter le VC présenté, au lieu d'un simple appel dans présenté. méthode du contrôleur de vue 

[self dismissViewControllerAnimated:NO completion:nil]

Pourquoi le premier choix est-il meilleur? Pourquoi Apple le recommande-t-il?

94
nikitahils

Je pense qu'Apple se cache un peu le dos ici pour une API potentiellement très compliquée. 

  [self dismissViewControllerAnimated:NO completion:nil]

Est-ce réellement un peu un violon. Bien que vous puissiez - légitimement - appeler cela sur le contrôleur de vue présenté, il ne fait que transmettre le message au contrôleur de vue présenté. Si vous voulez faire plus que rejeter le VC, vous devez le savoir et vous devez le traiter de la même manière qu'une méthode de délégué - car c'est à peu près ce que c'est, un fourre-tout assez rigide. méthode déléguée. 

Ils ont peut-être rencontré beaucoup de mauvais codes de la part de personnes ne comprenant pas vraiment comment cela est mis en place, d'où leur prudence. 

Mais bien sûr, si tout ce que vous avez à faire est de rejeter la chose, allez-y.

Ma propre approche est un compromis, du moins cela me rappelle ce qui se passe:

  [[self presentingViewController] dismissViewControllerAnimated:NO completion:nil]

[Rapide]

  self.presentingViewController?.dismiss(animated: false, completion:nil)
102
foundry

C'est pour la réutilisabilité du contrôleur de vue.

Votre contrôleur de vue ne devrait pas se soucier de savoir s’il est présenté comme un modal, poussé sur un contrôleur de navigation ou autre. Si votre contrôleur de vue se ferme, alors vous supposez qu'il est présenté de manière modale. Vous ne pourrez pas pousser ce contrôleur de vue sur un contrôleur de navigation.

En implémentant un protocole, vous laissez le contrôleur de vue parent décider de la manière dont il doit être présenté/poussé et rejeté/sauté.

46
Michael Enriquez

_ {Mis à jour pour Swift 3} _

Je suis venu ici juste pour écarter le contrôleur de vue actuel (présenté). Je fais cette réponse pour quiconque vient ici avec le même but.

Contrôleur de navigation

Si vous utilisez un contrôleur de navigation, c'est très simple.

Revenir au contrôleur de vue précédent:

// Swift
self.navigationController?.popViewController(animated: true)

// Objective-C
[self.navigationController popViewControllerAnimated:YES];

Retournez au contrôleur de vue racine:

// Swift
self.navigationController?.popToRootViewController(animated: true)

// Objective-C
[self.navigationController popToRootViewControllerAnimated:YES];

(Merci à cette réponse pour l'Objective-C.)

Contrôleur de vue modale

Lorsqu'un contrôleur de vue est présenté sous forme modale, vous pouvez le supprimer (du second contrôleur de vue) en appelant

// Swift
self.dismiss(animated: true, completion: nil)

// Objective-C
[self dismissViewControllerAnimated:YES completion:nil];

La documentation dit,

Le responsable de la vue présentation est responsable de la suppression de la vue contrôleur il a présenté. Si vous appelez cette méthode dans la vue présentée contrôleur lui-même, UIKit demande au contrôleur de la vue présentation de gérer le licenciement.

Donc, cela fonctionne pour que le contrôleur de vue présenté l'appelle sur lui-même. Ici est un exemple complet.

Les délégués

La question du PO concernait la complexité d'utiliser des délégués pour écarter un point de vue. 

Jusqu'à présent, je n'ai pas eu besoin d'utiliser de délégués, car j'ai généralement un contrôleur de navigation ou des contrôleurs de vue modale, mais si j'ai besoin d'utiliser le modèle de délégué à l'avenir, j'ajouterai une mise à jour.

41
Suragch

D'après mon expérience, il est utile lorsque vous devez le supprimer detoutViewController de votre choix et effectuer différentes tâches pour chaque contrôleur de vue qui le ferme. Tout viewController qui adopte le protocole peut ignorer la vue à sa manière. (ipad vs iphone, ou transmettre des données différentes lors du renvoi de vues différentes, appeler différentes méthodes lors du renvoi, etc.)

Modifier:

Donc, pour clarifier, si tout ce que vous voulez faire est de rejeter la vue, je ne vois pas la nécessité de configurer le protocole de délégué. Si vous devez faire différentes chosesaprèsvous le supprimez de différents contrôleurs de présentation, ce serait votre meilleure façon d'utiliser le délégué.

6
jhilgert00

essaye ça:

[self dismissViewControllerAnimated:true completion:nil];
6
Oshitha Wimalasuriya

Un point est que ceci est une bonne approche de codage. Il satisfait à de nombreux principes OOP, par exemple, SRP, séparation des préoccupations, etc. 

Ainsi, le contrôleur de vue présentant la vue doit être celui qui la rejette. 

Par exemple, une société immobilière qui loue une maison devrait être habilitée à la récupérer.

Swift 3.0 // Quitter le contrôleur de vue dans Swift 

self.navigationController?.popViewController(animated: true)
dismiss(animated: true, completion: nil)
2
Pranit

Extrait de View Guide de programmation du contrôleur , "Comment les contrôleurs de vue présentent-ils les autres contrôleurs de vue".

Chaque contrôleur de vue dans une chaîne de contrôleurs de vue présentés a des pointeurs vers les autres objets l'entourant dans la chaîne. En d'autre mots, un contrôleur de vue présenté qui présente une autre vue Le contrôleur a des objets valides à la fois dans presentsViewController et Propriétés presentsViewController. Vous pouvez utiliser ces relations pour tracez à travers la chaîne de vue les contrôleurs selon les besoins. Par exemple, si Si l'utilisateur annule l'opération en cours, vous pouvez supprimer tous les objets de la chaîne en rejetant le premier contrôleur de vue présenté . Refuser un contrôleur de vue exclut non seulement ce contrôleur de vue mais aussi tous les contrôleurs de vue présentés.

Donc, d’une part, cela donne un beau design équilibré, un bon découplage, etc. Mais, d’autre part, c’est très pratique, car vous pouvez rapidement revenir à un certain point de navigation. 

Personnellement, je préférerais utiliser dérouler les séquences plutôt que d'essayer de revenir en arrière dans l'arborescence présentation des contrôleurs de vue, dont Apple parle dans ce chapitre d'où provient la citation. 

2
svena

En plus de la réponse de Michael Enriquez, je peux penser à une autre raison pour laquelle cela pourrait être un bon moyen de vous protéger d'un état indéterminé:

Dites ViewControllerA présente ViewControllerB de manière modale. Mais, comme vous n'avez peut-être pas écrit le code pour ViewControllerA, vous n'êtes pas au courant du cycle de vie de ViewControllerA. Il peut perdre 5 secondes (par exemple) après avoir présenté votre contrôleur de vue, ViewControllerB.

Dans ce cas, si vous utilisiez simplement dismissViewController de ViewControllerB pour se rejeter, vous vous retrouveriez dans un état non défini - peut-être pas un crash ou un écran noir, mais un état non défini de votre point de vue.

Si, au lieu de cela, vous utilisiez le modèle de délégué, vous seriez au courant de l'état de ViewControllerB et vous pourrez programmer pour un cas comme celui que j'ai décrit.

1
Mayur

Rapide

let rootViewController:UIViewController = (UIApplication.shared.keyWindow?.rootViewController)!

        if (rootViewController.presentedViewController != nil) {
            rootViewController.dismiss(animated: true, completion: {
                //completion block.
            })
        }
0
Rishi Chaurasia

Si vous utilisez une utilisation modale, désactivez-la.

[self dismissViewControllerAnimated:NO completion:nil];
0
ErasmoOliveira

C'est beaucoup d'argent. La délégation convient bien en cas de besoin, mais si cela complique le code - et c'est vrai -, il doit y avoir une raison.

Je suis sûr que Apple a ses raisons. Mais il est plus clair et concis de demander simplement au VC présenté de rejeter la plainte à moins qu’il n’y ait une véritable raison de le faire et que personne aujourd’hui n’en a présenté de tel que je puisse le voir. 

Les protocoles sont excellents quand ils sont nécessaires, mais la conception orientée objet ne consistait jamais à faire en sorte que les modules communiquent inutilement les uns avec les autres. 

Tom Love (co-développeur de l’objectif C) a déjà déclaré que l’objectif C était «élégant», «petit», «net» et «bien défini» (en comparaison avec C++). Facile à dire. La délégation est une fonctionnalité utile qui semble avoir été surexploitée "simplement parce que" et même si j'aime travailler dans ce langage, je redoute l'idée d'abattre l'obligation de recourir à une syntaxe inutile pour rendre les choses plus complexes qu'elles ne le devraient.

0
RegularExpression