Programowo wróć do poprzedniego ViewController w Swift

211

Wysyłam użytkownika do strony jednym kliknięciem przycisku. Ta strona jest UITableViewController .

Teraz, jeśli użytkownik stuknie komórkę, chciałbym go odepchnąć z powrotem na poprzednią stronę.

Myślałem o czymś takim, self.performSegue("back")....ale wydaje się to złym pomysłem.

Jaki jest właściwy sposób to zrobić?

chrześcijanin
źródło
13
self.navigationController? .popViewControllerAnimated (true)
Kalpesh

Odpowiedzi:

526

Swift 3:

Jeśli chcesz wrócić do poprzedniego kontrolera widoku

_ = navigationController?.popViewController(animated: true)

Jeśli chcesz wrócić do kontrolera widoku głównego

_ = navigationController?.popToRootViewController(animated: true)
Praveen Gowda IV
źródło
1
Jak mogę wysłać dane z powrotem do poprzedniego kontrolera, gdy komórka jest stuknięta? jeśli korzystamy z NavigationController? .popViewControllerAnimated (true)
JDDelgado
4
@JDDelgado W ten sposób wysyłasz dane z powrotem do użytkownika, stackoverflow.com/questions/12561735/…
Mohamad Kaakati
36
W przypadku Swift 3 jest to.popViewController(animated: true)
Sasho,
9
Aby uciszyć wszelkie ostrzeżenia:_ = self.navigationController?.popToRootViewController(animated: true)
Andrew K
1
Ignorujemy wartość zwracaną; _ = jest szybka konwencja w tym zakresie.
Andrew K
53

Swift 3 , Swift 4

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

NavigationController jest opcjonalny, ponieważ może go nie być.

Wiaczesław
źródło
@ Vyacheslva dostaję błąd „niejawne użycie„ seft ”w zamknięciu, użyj„ self ”, aby wyraźna semantyka przechwytywania była wyraźna”
Sandip Subedi 20.04.17
@SandipSubedi wykorzystanie [weak self]iself?.navigationController?.
Wiaczesław
to było przydatne Ale chcę przesłać niektóre zmienne z nawigacją Ale teraz nie mogę - użyłem override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let vc = segue.destination as? Ale kiedy używam tego, nie mogę tego użyć
Saeed Rahmatolahi
jak zatem dodać nawigacjęController?
użytkownik25
@ użytkownik25 dodać? co masz na myśli?
Wiaczesław
37

Szybki 3

Być może spóźniłem się z odpowiedzią, ale w przypadku szybkiego 3 możesz to zrobić w ten sposób:

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)
}
Pełna moc
źródło
3
To nie jest „w pełni” poprawne. Jeśli zaprezentujesz kontroler widoku, który zawiera własną nawigację, a po naciśnięciu kontrolera widoku skorzystasz z tej metody dismiss:, nie tylko odrzuci on bieżący kontroler widoku, ale także kontroler widoku głównego, i nie o to tu pytano.
Ernesto Fernandez
2
Pytanie nie pytało, czy użytkownik miał kontroler nawigacji. To najprostsza i najlepsza odpowiedź na brak kontrolera nawigacji. To naprawdę powinna być zaakceptowana odpowiedź.
Droid Chris
Dzięki Droid - Cześć ernestofndz, możesz mieć rację mówiąc, że rootVC zostanie również odrzucony, ale tak się nie dzieje ze mną, to tylko odrzuca bieżące PCV, dodam i usuwam elementy programowo, i może to nie być to samo podejście z normalnym dodawaniem elementów do scenorysu .. popraw moje zrozumienie, jeśli się mylę ... dla tabeli Zobacz, czy użytkownik musi przekazać szczegóły do ​​innego widoku, to jest inny przypadek i nie ma żadnego związku z tym, co opublikowałem i w 100% zgadza się z tobą .. zrozumiałem, że w tym przypadku wymagany jest przycisk Wstecz :)
Fullpower
może możesz dodać małe wprowadzenie .. ponieważ istnieją odrzucić i nawigowaćController? .popViewController
marlonpya 11.09.17
dismiss(animated: true, completion: nil)nie działa po rotacji!
user924,
31

Szybki 4

istnieją dwa sposoby powrotu / powrotu do poprzedniego ViewController:

  1. Pierwszy przypadek : jeśli używałeś: self.navigationController?.pushViewController(yourViewController, animated: true) w tym przypadku musisz użyćself.navigationController?.popViewController(animated: true)
  2. Drugi przypadek : jeśli używałeś: self.present(yourViewController, animated: true, completion: nil) w tym przypadku musisz użyćself.dismiss(animated: true, completion: nil)

W pierwszym przypadku upewnij się, że wbudowałeś ViewController do NavigationController w swojej serii ujęć

Braham Youssef
źródło
19

W przypadku, gdy przedstawiłeś UIViewControllerz wewnątrz UIViewControllertj.

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

Wystarczy wywołać dismissfunkcję:

// Other View Controller
self.dismiss(animated: true)
spencer.sm
źródło
self.dismiss(animated: true)- nie działa po rotacji
924
17

szybkie 5 i więcej

przypadek 1: korzystanie z kontrolerem nawigacyjnym

self.navigationController?.popViewController(animated: true)

przypadek 2: użycie z obecnym kontrolerem widoku

self.dismiss(animated: true, completion: nil)
midhun p
źródło
11

Jeśli Segue to „Show” lub „Push”, możesz wywołać „popViewController (animated: Bool)” na Instancji UINavigationController. Lub jeśli segue jest rodzajem „obecnym”, to wywołaj „odrzuć (animowane: Bool, zakończenie: (() -> Void)?)” Z instancją UIViewController

Pankaj
źródło
7

dla swift 3 wystarczy napisać następujący wiersz kodu

_ = navigationController?.popViewController(animated: true)
Amr Angry
źródło
2

Spróbuj tego: w poprzednim widoku użyj tego:

navigationController?.popViewController(animated: true)  

pop do roota użyj tego kodu:

navigationController?.popToRootViewController(animated: true) 
Ahsan
źródło
2

Swift 4.0 Xcode 10.0 z TabViewController jako ostatnim widokiem

Jeśli twój ostatni ViewController jest zapisany w TabViewController, poniższy kod wyśle ​​cię do katalogu głównego ...

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

Ale jeśli naprawdę chcesz wrócić do ostatniego widoku (może to być widok Tab1, Tab2 lub Tab3 ..), musisz napisać poniższy kod:

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

To działa dla mnie, korzystałem z widoku po jednym z moich TabView :)

Gabo MC
źródło
1

W przypadku pytań dotyczących sposobu osadzania viewController w navigationController w serii ujęć:

  1. Otwórz scenorys, w którym znajduje się twój inny viewController
  2. Stuknij viewController, od którego chcesz uruchomić kontroler nawigacji
  3. Na górze Xcode dotknij „Edytor”
  4. -> Stuknij w osadz
  5. -> Wybierz „Kontroler nawigacji
Manveer Singh Pandher
źródło
1

Ten działa dla mnie (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")
        }
      }
    }
}
Igor Samcewicz
źródło
0

Zrobiłem to w ten sposób

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)
}
Jarosław Sarnicki
źródło
0

Chciałbym zaproponować inne podejście do tego problemu. Zamiast używać kontrolera nawigacyjnego do otwierania kontrolera widoku, użyj sekwencji rozwijania. To rozwiązanie ma kilka, ale naprawdę ważnych zalet:

  1. Kontroler pochodzenia może wrócić do dowolnego innego kontrolera docelowego (nie tylko poprzedniego), nie wiedząc nic o miejscu docelowym.
  2. Sekwencje push i pop są zdefiniowane w serii ujęć, więc nie ma kodu nawigacyjnego w kontrolerach widoku.

Więcej informacji można znaleźć w sekcji Odwijanie segmentów krok po kroku . Sposób, w jaki lepiej to wyjaśniono w poprzednim linku, w tym sposób przesyłania danych z powrotem, ale tutaj przedstawię krótkie wyjaśnienie.

1) Przejdź do kontrolera widoku docelowego (nie źródłowego) i dodaj segment rozwijania:

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

2) CTRL przeciągnij z kontrolera widoku sama do ikony wyjścia w kontrolerze widoku pochodzenie:

Odpręż się od kontrolera widoku

3) Wybierz funkcję rozwijania, którą właśnie utworzyłeś kilka chwil temu:

Wybierz funkcję odwijania

4) Wybierz segment odwijania i nadaj mu nazwę:

Nazywanie odwijania segue

5) Przejdź do dowolnego miejsca kontrolera widoku źródłowego i wywołaj odwijanie:

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

Przekonałem się, że takie podejście przynosi wiele korzyści, gdy nawigacja zaczyna się komplikować.

Mam nadzieję, że to komuś pomoże.

XME
źródło
-3

Mogę przekierować na stronę główną pisząc kod w „viewDidDisappear” kontrolowanego nawigatora,

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

Mahe
źródło
Powoduje to, że kontroler nawigacji wyskakuje do katalogu głównego, nawet jeśli chcesz przejść do przodu w hierarchii.
bkSwifty 21.04.17