2
votes

Comment ignorer 2 contrôleurs de vue modale sans animation étrange

J'ai recréé la question et décrit son essence plus précisément.

J'ai deux contrôleurs de vue présentés de manière modale sur Swift 4, sans storyboard (ne peut pas utiliser de déroulement) et sans navigation contrôleur

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

La raison pour laquelle nous n'utilisons pas contrôleur de navigation , c'est parce que nous quelle simple animation de bas en haut top et au lieu de casser l'animation standard de droite à gauche , nous avons décidé d'utiliser present.

Je voudrais ignorer 2 afficher les contrôleurs et passer de C à A.

S'il vous plaît, ne marquez pas cette question comme dupliquée avant de lire ma question attentivement. J'ai trouvé un ton similaire, mais aucun n'a résolu mon problème. Certains d'entre eux Objective-C ou certains des suggèrent d'utiliser:

self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)

Ou:

XXX

Cela fonctionne, mais cela crée une animation étrange. Il suffit de supprimer C et d'animer le rejet pour B:

 entrez la description de l'image ici

Résultat attendu:

 entrez la description de l'image ici


4 commentaires

nous n'utilisons pas de storyboard. Tout le code est écrit par programme.


stackoverflow.com/a/37487975 couvre ce problème; c'est l'une des réponses au premier duplicata que j'ai fourni hier. Il y a presque certainement plus de couverture du problème dans l'un des nombreux autres doublons. Veuillez ne pas republier; modifiez plutôt votre question précédente .


C'est Objective-C


L'API est identique dans les deux langues.


4 Réponses :


0
votes

Si vous n'utilisez pas de contrôleur de navigation et que vous souhaitez fermer tous les ViewControllers pour afficher le ViewController racine (en supposant que A est la racine) :

self.view.window?.rootViewController?.dismiss(animated: true, completion: nil)


1 commentaires

Malheureusement, A n'est pas root



0
votes

Utilisez ceci dans la méthode d'action de bouton. Le VC actuel sera supprimé lorsque vous rejetez le VC parent. Cela supprimera les deux VC dans une seule animation.

self.presentingViewController? .presentingViewController? .dismiss (animé: vrai, complétion: nil)


0 commentaires

4
votes

Idée: vous devez ignorer le troisième contrôleur avec animation et après avoir ignoré, vous devez ignorer le deuxième sans animation. Pendant que le troisième contrôleur est en cours de suppression, le deuxième ne doit pas être visible.


Tout d'abord, définissez le Style de présentation du deuxième contrôleur de vue sur Over Current Context lorsque vous ' le présenter (puisque nous devrons masquer sa vue lorsque nous ignorerons le troisième contrôleur)

class VC2: UIViewController {

    @objc func buttonPressed(_ sender: UIButton) {

        var vc3 = VC3()

        vc3.willDismiss = {
            self.view.isHidden = true
        }

        vc3.didDismiss = {
            self.dismiss(animated: false)
        }

        present(vc3, animated: true)
    }

}

continuez à créer des propriétés de rappel pour willDismiss et didDismiss à l'intérieur du troisième contrôleur. Ce rappel sera appelé avant et après avoir rejeté le troisième contrôleur

class VC3: UIViewController {

    var willDismiss: (() -> Void)?
    var didDismiss:  (() -> Void)?

    @IBAction func dismissButtonPressed(_ sender: UIButton) {

        willDismiss?()

        dismiss(animated: true) {
            self.didDismiss?()
        }
    }

}

puis dans le deuxième contrôleur de vue à l'endroit où vous présentez le troisième contrôleur de vue, définissez les propriétés de rappel du troisième contrôleur: déclarez quoi se produit lorsque le troisième contrôleur va ignorer: vous devez masquer la vue du deuxième, puis après avoir ignoré le troisième, vous devez ignorer le deuxième sans animation (la vue peut rester cachée car le contrôleur de vue sera désinitialisé)

XXX


 entrez la description de l'image ici


Quoi qu'il en soit, la deuxième option utilise UINavigationController et puis appelez simplement sa méthode popToViewController(_:animated:).


0 commentaires

1
votes

Créez un instantané à partir de la vue actuellement visible et ajoutez-le en tant que sous-vue au premier contrôleur de vue présenté. Pour constater que vous pouvez simplement "parcourir" les contrôleurs de vue de présentation et ignorer le contrôleur initial:

@IBAction func dismissViewControllers(_ sender: UIButton) {
    var initialPresentingViewController = self.presentingViewController
    while let previousPresentingViewController = initialPresentingViewController?.presentingViewController {
        initialPresentingViewController = previousPresentingViewController
    }


    if let snapshot = view.snapshotView(afterScreenUpdates: true) {
        initialPresentingViewController?.presentedViewController?.view.addSubview(snapshot)
    }

    initialPresentingViewController?.dismiss(animated: true)
}

Voici le résultat avec des animations lentes activées pour le rejet: https://www.dropbox.com/s/tjkthftuo9kqhsg/result. mov? dl = 0


6 commentaires

Salut André, avec cette solution, le deuxième contrôleur est visible lors du rejet et c'est exactement le problème qu'OP a. Vous pouvez vérifier ma réponse si elle vous donne une meilleure vue du problème.


@RobertDresler Vous avez raison. Mis à jour ma réponse.


Salut. Merci pour cette excellente solution, mais comment puis-je résoudre ce problème pour modalPresentationStyle = .overCurrentContext?


@DenAndreychuk Avez-vous vraiment besoin de .overCurrentContext ? Dans votre exemple, cela n'est pas nécessaire puisque les contrôleurs de vue présentés couvrent entièrement les contrôleurs de vue en dessous.


Ouais. Nous ajoutons un geste pour faire glisser vers le bas et nous avons besoin de contenu pour l'arrière-plan


Pouvez-vous me dire / me montrer quel est le problème actuel?