Gehen Sie programmgesteuert zum vorherigen ViewController in Swift zurück


211

Ich sende den Benutzer per Knopfdruck auf eine Seite. Diese Seite ist ein UITableViewController .

Wenn der Benutzer nun auf eine Zelle tippt, möchte ich ihn auf die vorherige Seite zurückschieben.

Ich habe über so etwas nachgedacht, self.performSegue("back")....aber das scheint eine schlechte Idee zu sein.

Was ist der richtige Weg, um es zu tun?


13
self.navigationController? .popViewControllerAnimated (true)
Kalpesh

Antworten:


526

Swift 3:

Wenn Sie zum vorherigen Ansichts-Controller zurückkehren möchten

_ = navigationController?.popViewController(animated: true)

Wenn Sie zum Root View Controller zurückkehren möchten

_ = navigationController?.popToRootViewController(animated: true)

1
Wie kann ich Daten an den vorherigen Controller zurücksenden, wenn auf die Zelle getippt wird? Wenn wir den Navigationscontroller verwenden? .popViewControllerAnimated (true)
JDDelgado

4
@ JDDelgado So senden Sie die Daten mit dem Benutzer zurück, stackoverflow.com/questions/12561735/…
Mohamad Kaakati

36
Für Swift 3 ist es.popViewController(animated: true)
Sasho

9
Um alle Warnungen zu vertuschen:_ = self.navigationController?.popToRootViewController(animated: true)
Andrew K

1
Wir ignorieren den Rückgabewert. _ = ist die Konvention dafür schnell.
Andrew K

53

Swift 3 , Swift 4

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

navigationController ist optional, da möglicherweise keiner vorhanden ist.


@Vyacheslva Ich erhalte die Fehlermeldung "implizite Verwendung von 'seft' in Closure, benutze 'self', um die Erfassungssemantik explizit zu machen"
Sandip Subedi

@ SandipSubedi verwenden [weak self]undself?.navigationController?.
Vyacheslav

Das war nützlich. Aber ich möchte einige Variablen mit Navigation senden. Aber jetzt kann ich nicht - ich habe verwendet. override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let vc = segue.destination as? Aber wenn ich dies verwende, kann ich das nicht verwenden.
Saeed Rahmatolahi

Wie füge ich dann den Navigationscontroller hinzu?
Benutzer25

@ user25 hinzufügen? Was meinst du?
Vyacheslav

37

Swift 3

Ich könnte zu spät in der Antwort sein, aber für Swift 3 können Sie es so machen:

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
Das ist nicht "ganz" richtig. Wenn Sie einen Ansichts-Controller präsentieren, der eine eigene Navigation enthält, und nachdem Sie einen Ansichts-Controller gedrückt haben, der diese Methode verwendet dismiss:, wird nicht nur der aktuelle Ansichts-Controller, sondern auch der Root-Ansichts-Controller geschlossen, und dies wurde hier nicht gefragt.
Ernesto Fernandez

2
Bei der Frage wurde nicht gefragt, ob der Benutzer einen Navigationscontroller hatte. Dies ist die einfachste und beste Antwort für keinen Navigationscontroller. Dies sollte wirklich die akzeptierte Antwort sein.
Droid Chris

Danke Droid - Hallo ernestofndz, Sie haben vielleicht Recht, wenn Sie sagen, dass die rootVC auch entlassen wird, aber das passiert bei mir nicht, es entlässt nur die aktuelle VC, ich füge Elemente programmgesteuert hinzu und entferne sie und es ist möglicherweise nicht der gleiche Ansatz Mit den normalen Hinzufügungselementen im Storyboard. Korrigieren Sie mein Verständnis, wenn ich falsch liege. Für die Tabellenansicht. Wenn der Benutzer Details an eine andere Ansicht übergeben muss, ist dies ein anderer Fall und hat keine Verknüpfung zu dem, was ich gepostet habe, und wird zu 100% zustimmen mit dir ... was ich verstanden habe war, dass in diesem Fall ein Zurück-Button erforderlich ist :)
Fullpower

Vielleicht können Sie eine kleine Einführung hinzufügen .. weil existieren entlassen & NavigationController? .popViewController
Marlonpya

dismiss(animated: true, completion: nil)funktioniert nach der Rotation nicht!
user924

31

Swift 4

Es gibt zwei Möglichkeiten, zum vorherigen ViewController zurückzukehren:

  1. Erster Fall : Wenn Sie verwendet haben: self.navigationController?.pushViewController(yourViewController, animated: true) In diesem Fall müssen Sie verwendenself.navigationController?.popViewController(animated: true)
  2. Zweiter Fall : Wenn Sie verwendet haben: self.present(yourViewController, animated: true, completion: nil) In diesem Fall müssen Sie verwendenself.dismiss(animated: true, completion: nil)

Stellen Sie im ersten Fall sicher, dass Sie Ihren ViewController in einen Navigationscontroller in Ihrem Storyboard eingebettet haben


19

In dem Fall, in dem Sie eine UIViewControllervon innerhalb eines UIViewControllerdh präsentiert haben.

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

Rufen Sie einfach die dismissFunktion auf:

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

self.dismiss(animated: true)- funktioniert nicht nach der Rotation
user924

17

schnell 5 und höher

Fall 1: Verwendung mit dem Navigationscontroller

self.navigationController?.popViewController(animated: true)

Fall 2: Verwendung mit dem aktuellen Ansichts-Controller

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

11

Wenn Segue eine Art 'Show' oder 'Push' ist, können Sie "popViewController (animiert: Bool)" auf Instanz von UINavigationController aufrufen. Oder wenn segue irgendwie "vorhanden" ist, rufen Sie mit der Instanz von UIViewController "entlassen (animiert: Bool, Vervollständigung: (() -> Void)?)" Auf


7

Für Swift 3 müssen Sie nur die folgende Codezeile schreiben

_ = navigationController?.popViewController(animated: true)

2

Versuchen Sie Folgendes: Verwenden Sie für die vorherige Ansicht Folgendes:

navigationController?.popViewController(animated: true)  

pop to root benutze diesen Code:

navigationController?.popToRootViewController(animated: true) 

2

Swift 4.0 Xcode 10.0 mit einem TabViewController als letzte Ansicht

Wenn Ihr letzter ViewController in einen TabViewController eingebettet ist, werden Sie mit dem folgenden Code zum Stammverzeichnis gesendet ...

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

Wenn Sie jedoch wirklich zur letzten Ansicht zurückkehren möchten (dies kann die Ansicht Tab1, Tab2 oder Tab3 sein), müssen Sie den folgenden Code schreiben:

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

Das funktioniert bei mir, ich habe eine Ansicht nach einer meiner TabView verwendet :)


1

Bei Fragen zum Einbetten Ihres viewControllers in einen Navigationscontroller im Storyboard:

  1. Öffnen Sie Ihr Storyboard, in dem sich Ihre verschiedenen viewController befinden
  2. Tippen Sie auf den viewController, von dem aus Ihr Navigationscontroller starten soll
  3. Tippen Sie oben auf Xcode auf "Editor".
  4. -> Tippen Sie auf Einbetten in
  5. -> Tippen Sie auf "Navigation Controller"

1

Dieser funktioniert für mich (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

Ich habe es so gemacht

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

Ich möchte einen anderen Ansatz für dieses Problem vorschlagen. Verwenden Sie Abwicklungssegmente, anstatt einen Navigationscontroller zum Öffnen eines Ansichtscontrollers zu verwenden. Diese Lösung hat einige, aber wirklich wichtige Vorteile:

  1. Der Ursprungscontroller kann zu jedem anderen Zielcontroller (nicht nur zum vorherigen) zurückkehren, ohne etwas über das Ziel zu wissen.
  2. Push- und Pop-Segmente werden im Storyboard definiert, sodass in Ihren View-Controllern kein Navigationscode vorhanden ist.

Weitere Informationen finden Sie unter Schritt für Schritt Segmente abwickeln . Das Vorgehen wird im vorherigen Link besser erklärt, einschließlich des Zurücksendens von Daten. Hier werde ich jedoch eine kurze Erklärung abgeben.

1) Gehen Sie zum Ziel- View-Controller (nicht zum Ursprungs-View-Controller) und fügen Sie einen Abwicklungsbereich hinzu:

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

2) Ziehen Sie die STRG-Taste vom Ansichts-Controller selbst zum Exit-Symbol im Ursprungs-Ansichts-Controller:

Entspannen Sie sich vom View Controller

3) Wählen Sie die Abwicklungsfunktion aus, die Sie vor wenigen Augenblicken erstellt haben:

Wählen Sie die Abwickelfunktion

4) Wählen Sie den Abwicklungsbereich und geben Sie ihm einen Namen:

Naming Unwind Segue

5) Gehen Sie zu einer beliebigen Stelle des Ursprungsansichts-Controllers und rufen Sie den Abwicklungsbereich auf:

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

Ich habe festgestellt, dass sich dieser Ansatz sehr auszahlt, wenn Ihre Navigation kompliziert wird.

Ich hoffe das hilft jemandem.


-3

Ich kann zur Stammseite umleiten, indem ich Code in "viewDidDisappear" des navigierten Controllers schreibe.

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


Dies führt dazu, dass der Navigationscontroller zum Stammverzeichnis wechselt, selbst wenn Sie in der Hierarchie vorwärts gehen möchten.
bkSwifty
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.