Regrese programáticamente a ViewController anterior en Swift

211

Envío al usuario a una página con un clic de botón. Esta página es un UITableViewController .

Ahora, si el usuario toca una celda, me gustaría empujarlo a la página anterior.

Pensé en algo así, self.performSegue("back")....pero parece ser una mala idea.

¿Cuál es la forma correcta de hacerlo?

cristiano
fuente
13
self.navigationController? .popViewControllerAnimated (verdadero)
Kalpesh

Respuestas:

527

Swift 3:

Si desea volver al controlador de vista anterior

_ = navigationController?.popViewController(animated: true)

Si desea volver al controlador de vista raíz

_ = navigationController?.popToRootViewController(animated: true)
Praveen Gowda IV
fuente
1
¿Cómo puedo enviar datos a anteriorController cuando se toca la celda? si estamos usando el NavigationController? .popViewControllerAnimated (verdadero)
JDDelgado
44
@JDDelgado Así es como se envían los datos al usuario, stackoverflow.com/questions/12561735/…
Mohamad Kaakati
36
Para Swift 3 es.popViewController(animated: true)
Sasho
9
Para callar cualquier advertencia:_ = self.navigationController?.popToRootViewController(animated: true)
Andrew K
1
Estamos ignorando el valor de retorno; _ = es la convención rápida para eso.
Andrew K
53

Swift 3 , Swift 4

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

navigationController es opcional porque puede que no haya uno.

Vyacheslav
fuente
@Vyacheslva obtengo un error "uso implícito de 'seft' en el cierre, uso 'self' para hacer explícita la semántica de captura"
Sandip Subedi
@SandipSubedi usa [weak self]yself?.navigationController?.
Vyacheslav
esto fue útil Pero quiero enviar algunas variables con la navegación Pero ahora no puedo - Solía override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let vc = segue.destination as? Pero cuando uso esto no puedo usar eso
Saeed Rahmatolahi
¿Cómo agregar navigationController entonces?
usuario25
@ user25 agregar? ¿Qué quieres decir?
Vyacheslav
37

Swift 3

Podría llegar tarde en la respuesta, pero para Swift 3 puede hacerlo de esta manera:

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)
}
Poder completo
fuente
3
Eso no es "completamente" correcto. Si presenta un controlador de vista que contiene su propia navegación, y después de presionar un controlador de vista use ese método dismiss:, no solo descartará el controlador de vista actual, sino también el controlador de vista raíz, y no es lo que se le preguntó aquí.
Ernesto Fernández
2
La pregunta no preguntaba si el usuario tenía un controlador de navegación. Esta es la respuesta más simple y mejor para ningún controlador de navegación. Esta realmente debería ser la respuesta aceptada.
Droid Chris
Gracias Droid: Hola Ernestofndz, puede que tengas razón al decir que el rootVC también será descartado, pero esto no sucede conmigo, solo descarta el CurrentVC, estoy agregando y eliminando elementos mediante programación, y podría no ser el mismo enfoque con los elementos de adición normales en el guión gráfico ... corrija mi comprensión si estoy equivocado ... para la tabla Vista si el usuario necesita pasar detalles a otra Vista, este es otro caso y no tiene ningún vínculo con lo que he publicado y estaré 100% de acuerdo contigo ... lo que entendí fue que se requiere un botón Atrás en este caso :)
Fullpower
tal vez pueda agregar una pequeña introducción ... porque existe despedir & navigationController? .popViewController
marlonpya
dismiss(animated: true, completion: nil)no funciona después de la rotación!
user924
32

Swift 4

Hay dos formas de volver / volver al ViewController anterior:

  1. Primer caso : si usó: self.navigationController?.pushViewController(yourViewController, animated: true) en este caso necesita usarself.navigationController?.popViewController(animated: true)
  2. Segundo caso : si usó: self.present(yourViewController, animated: true, completion: nil) en este caso necesita usarself.dismiss(animated: true, completion: nil)

En el primer caso, asegúrese de haber incrustado su ViewController en un NavigationController en su guión gráfico

Braham Youssef
fuente
19

En el caso en que presentó un UIViewControllerdesde dentro de un UIViewControllerie ..

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

Simplemente llame a la dismissfunción:

// Other View Controller
self.dismiss(animated: true)
spencer.sm
fuente
self.dismiss(animated: true)- no funciona después de la rotación
usuario924
17

Swift 5 y superior

caso 1: uso con controlador de navegación

self.navigationController?.popViewController(animated: true)

caso 2: uso con el controlador de vista actual

self.dismiss(animated: true, completion: nil)
Midhun p
fuente
11

Si Segue es una especie de 'Show' o 'Push', puede invocar "popViewController (animado: Bool)" en la instancia de UINavigationController. O si segue es una especie de "presente", llame a "despedir (animado: Bool, finalización: (() -> Void)?)" Con la instancia de UIViewController

Pankaj
fuente
7

para Swift 3 solo necesita escribir la siguiente línea de código

_ = navigationController?.popViewController(animated: true)
Amr enojado
fuente
2

Pruebe esto: para la vista anterior use esto:

navigationController?.popViewController(animated: true)  

pop to root usa este código:

navigationController?.popToRootViewController(animated: true) 
Ahsan
fuente
2

Swift 4.0 Xcode 10.0 con un TabViewController como última vista

Si su último ViewController está incrustado en un TabViewController, el siguiente código lo enviará a la raíz ...

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

Pero si realmente desea volver a la última vista (que podría ser la vista Tab1, Tab2 o Tab3 ...), debe escribir el siguiente código:

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

Esto funciona para mí, estaba usando una vista después de uno de mis TabView :)

Gabo MC
fuente
1

Para preguntas sobre cómo incrustar su viewController en un NavigationController en el guión gráfico:

  1. Abra su guión gráfico donde se encuentran sus diferentes viewController
  2. Toque el viewController desde el que desea que comience su controlador de navegación
  3. En la parte superior de Xcode, toca "Editor"
  4. -> Toque incrustar en
  5. -> Toque "Controlador de navegación
Manveer Singh Pandher
fuente
1

Este funciona para mí (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 Samtsevich
fuente
0

Lo hice asi

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)
}
Yaroslav Sarnitskiy
fuente
0

Me gustaría sugerir otro enfoque para este problema. En lugar de usar el controlador de navegación para mostrar un controlador de vista, use desenrollar segues. Esta solución tiene algunas ventajas, pero realmente importantes:

  1. El controlador de origen puede volver a cualquier otro controlador de destino (no solo el anterior) sin saber nada sobre el destino.
  2. Los segmentos push y pop se definen en el guión gráfico, por lo que no hay código de navegación en los controladores de vista.

Puede encontrar más detalles en Unwind Segues paso a paso . El cómo hacerlo se explica mejor en el enlace anterior, incluido cómo enviar datos de regreso, pero aquí haré una breve explicación.

1) Vaya al controlador de vista de destino (no el origen) y agregue un segmento de desenrollado:

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

2) CTRL arrastre desde el controlador de vista en al icono de salida en el controlador de vista de origen:

Relájese del controlador de vista

3) Seleccione la función de desenrollar que acaba de crear hace unos momentos:

Seleccionar función de desenrollado

4) Seleccione el desenrollar segue y asígnele un nombre:

Nombrar desenrollar segue

5) Vaya a cualquier lugar del controlador de vista de origen y llame al desenrollar segue:

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

He encontrado que este enfoque es muy rentable cuando su navegación comienza a complicarse.

Espero que esto ayude a alguien.

XME
fuente
-3

Puedo redirigir a la página raíz escribiendo código en "viewDidDisappear" del controlador navegado,

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

Mahé
fuente
Esto hace que el controlador de navegación salte a la raíz, incluso si desea avanzar en la jerarquía.
bkSwifty