Retour par programme au ViewController précédent dans Swift


211

J'envoie l'utilisateur vers une page en cliquant sur un bouton. Cette page est un UITableViewController .

Maintenant, si l'utilisateur tape sur une cellule, je voudrais le repousser à la page précédente.

J'ai pensé à quelque chose comme self.performSegue("back")....mais cela semble être une mauvaise idée.

Quelle est la bonne façon de procéder?


13
self.navigationController? .popViewControllerAnimated (true)
Kalpesh

Réponses:


527

Swift 3:

Si vous souhaitez revenir au contrôleur de vue précédent

_ = navigationController?.popViewController(animated: true)

Si vous souhaitez revenir au contrôleur de vue racine

_ = navigationController?.popToRootViewController(animated: true)

1
Comment puis-je envoyer des données à previousController lorsque la cellule est tapée? si nous utilisons le navigationController? .popViewControllerAnimated (true)
JDDelgado

4
@JDDelgado C'est ainsi que vous renvoyez les données avec l'utilisateur, stackoverflow.com/questions/12561735/…
Mohamad Kaakati

36
Pour Swift 3 c'est.popViewController(animated: true)
Sasho

9
Pour ignorer les avertissements:_ = self.navigationController?.popToRootViewController(animated: true)
Andrew K

1
Nous ignorons la valeur de retour; _ = est la convention rapide pour cela.
Andrew K

53

Swift 3 , Swift 4

if movetoroot { 
    navigationController?.popToRootViewController(animated: true)
} else {
    navigationController?.popViewController(animated: true)
}

navigationController est facultatif car il n'y en a peut-être pas.


@Vyacheslva j'obtiens une erreur "utilisation implicite de 'seft' dans la fermeture, utilisez 'self' pour rendre la sémantique de capture explicite"
Sandip Subedi

@SandipSubedi use [weak self]andself?.navigationController?.
Vyacheslav

c'était utile Mais je veux envoyer des variables avec la navigation Mais maintenant je ne peux pas - j'ai utilisé override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let vc = segue.destination as? Mais quand j'utilise ceci je ne peux pas l'utiliser
Saeed Rahmatolahi

comment ajouter navigationController alors?
user25

@ user25 add? Que voulez-vous dire?
Vyacheslav

37

Swift 3

Je suis peut-être en retard dans la réponse, mais pour swift 3, vous pouvez le faire de cette façon:

override func viewDidLoad() {
    super.viewDidLoad()

    navigationItem.leftBarButtonItem = UIBarButtonItem(title: "< Back", style: .plain, target: self, action: #selector(backAction))

    // Do any additional setup if required.
}

func backAction(){
    //print("Back Button Clicked")
    dismiss(animated: true, completion: nil)
}

3
Ce n'est pas «entièrement» correct. Si vous présentez un contrôleur de vue qui contient sa propre navigation, et après avoir appuyé sur un contrôleur de vue, utilisez cette méthode dismiss:, non seulement le contrôleur de vue actuel sera rejeté, mais également le contrôleur de vue racine, et ce n'est pas ce qui a été demandé ici.
Ernesto Fernandez

2
La question ne demandait pas si l'utilisateur avait un contrôleur de navigation. C'est la réponse la plus simple et la meilleure pour aucun contrôleur de navigation. Cela devrait vraiment être la réponse acceptée.
Droid Chris

Merci Droid - Salut ernestofndz, vous avez peut-être raison de dire que le rootVC sera également rejeté, mais cela ne se produit pas avec moi, il ne fait que rejeter le VC actuel, j'ajoute et supprime des éléments par programme, et ce n'est peut-être pas la même approche avec les éléments d'ajout normaux sur le storyboard .. corriger ma compréhension si je me trompe ... pour la tableVoir si l'utilisateur doit passer des détails à une autre vue alors c'est un autre cas et n'a aucun lien avec ce que j'ai publié et sera 100% d'accord avec vous..ce que j'ai compris était qu'un bouton Retour est nécessaire dans ce cas :)
Fullpower

Peut-être que vous pouvez ajouter une petite introduction .. parce qu'il existe un système de navigation et de navigation? .popViewController
marlonpya

dismiss(animated: true, completion: nil)ne fonctionne pas après rotation!
user924

32

Swift 4

il y a deux façons de revenir / revenir au ViewController précédent:

  1. Premier cas : si vous avez utilisé: self.navigationController?.pushViewController(yourViewController, animated: true) dans ce cas, vous devez utiliserself.navigationController?.popViewController(animated: true)
  2. Deuxième cas : si vous avez utilisé: self.present(yourViewController, animated: true, completion: nil) dans ce cas, vous devez utiliserself.dismiss(animated: true, completion: nil)

Dans le premier cas, assurez-vous d'avoir intégré votre ViewController à un navigationController dans votre storyboard


19

Dans le cas où vous avez présenté un UIViewControllerde l'intérieur d'un UIViewControllerie ..

// Main View Controller
self.present(otherViewController, animated: true)

Appelez simplement la dismissfonction:

// Other View Controller
self.dismiss(animated: true)

self.dismiss(animated: true)- ne fonctionne pas après la rotation
user924

17

rapide 5 et au-dessus

cas 1: utilisation avec le contrôleur de navigation

self.navigationController?.popViewController(animated: true)

cas 2: utilisation avec le contrôleur de vue actuel

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

11

Si Segue est une sorte de 'Show' ou 'Push', vous pouvez invoquer "popViewController (animated: Bool)" sur l'instance de UINavigationController. Ou si segue est une sorte de "présent" alors appelez "rejeter (animé: Bool, complétion: (() -> Vide)?)" Avec une instance de UIViewController


7

pour swift 3, il vous suffit d'écrire la ligne de code suivante

_ = navigationController?.popViewController(animated: true)

2

Essayez ceci: pour la vue précédente, utilisez ceci:

navigationController?.popViewController(animated: true)  

pop to root utilisez ce code:

navigationController?.popToRootViewController(animated: true) 

2

Swift 4.0 Xcode 10.0 avec un TabViewController comme dernière vue

Si votre dernier ViewController est intégré dans un TabViewController, le code ci-dessous vous enverra à la racine ...

navigationController?.popToRootViewController(animated: true)
navigationController?.popViewController(animated: true)

Mais si vous voulez vraiment revenir à la dernière vue (qui pourrait être la vue Tab1, Tab2 ou Tab3 ..), vous devez écrire le code ci-dessous:

_ = self.navigationController?.popViewController(animated: true)

Cela fonctionne pour moi, j'utilisais une vue après l'un de mes TabView :)


1

Pour toute question concernant la façon d'intégrer votre viewController à un navigationController dans le storyboard:

  1. Ouvrez votre storyboard où se trouvent vos différents ViewController
  2. Appuyez sur le viewController à partir duquel vous souhaitez que votre contrôleur de navigation démarre
  3. En haut de Xcode, appuyez sur "Editeur"
  4. -> Tap intégré
  5. -> Appuyez sur "Contrôleur de navigation

1

Celui-ci fonctionne pour moi (Swift UI)

struct DetailView: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

  var body: some View {
      VStack {
        Text("This is the detail view")
        Button(action: {
          self.presentationMode.wrappedValue.dismiss()
        }) {
          Text("Back")
        }
      }
    }
}

0

Je l'ai fait comme ça

func showAlert() {
    let alert = UIAlertController(title: "Thanks!", message: "We'll get back to you as soon as posible.", preferredStyle: .alert)

    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { action in
        self.dismissView()
    }))

    self.present(alert, animated: true)
}

func dismissView() {
    navigationController?.popViewController(animated: true)
    dismiss(animated: true, completion: nil)
}

0

Je voudrais suggérer une autre approche de ce problème. Au lieu d'utiliser le contrôleur de navigation pour faire apparaître un contrôleur de vue, utilisez des séquences de déroulement. Cette solution présente quelques avantages, mais vraiment importants:

  1. Le contrôleur d'origine peut revenir à n'importe quel autre contrôleur de destination (pas seulement le précédent) sans rien savoir de la destination.
  2. Les séquences push et pop sont définies dans le storyboard, donc pas de code de navigation dans vos contrôleurs de vue.

Vous pouvez trouver plus de détails dans Unwind Segues étape par étape . Le mode d'emploi est mieux expliqué dans l'ancien lien, y compris la façon de renvoyer des données, mais ici, je ferai une brève explication.

1) Accédez au contrôleur de vue de destination (et non à l'origine) et ajoutez une séquence de déroulement:

    @IBAction func unwindToContact(_ unwindSegue: UIStoryboardSegue) {
        //let sourceViewController = unwindSegue.source
        // Use data from the view controller which initiated the unwind segue
    }

2) Faites glisser CTRL du contrôleur de vue lui-même vers l'icône de sortie dans le contrôleur de vue d'origine:

Détendez-vous du contrôleur de vue

3) Sélectionnez la fonction de déroulement que vous venez de créer il y a quelques instants:

Sélectionnez la fonction de déroulement

4) Sélectionnez la séquence de déroulement et donnez-lui un nom:

Nommer segue segue

5) Allez à n'importe quel endroit du contrôleur de vue d'origine et appelez la séquence de déroulement:

performSegue(withIdentifier: "unwindToContact", sender: self)

J'ai trouvé cette approche très rentable lorsque votre navigation commence à se compliquer.

J'espère que ça aidera quelqu'un.


-3

Je peux rediriger vers la page racine en écrivant du code dans "viewDidDisappear" du contrôleur navigué,

override func viewDidDisappear(_ animated: Bool) { self.navigationController?.popToRootViewController(animated: true) }


Cela fait que le contrôleur de navigation saute à la racine, même si vous voulez avancer dans la hiérarchie.
bkSwifty
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.