Programaticamente, volte ao ViewController anterior no Swift

211

Eu envio o usuário para uma página com um clique no botão. Esta página é um UITableViewController .

Agora, se o usuário tocar em uma célula, eu gostaria de empurrá-lo de volta para a página anterior.

Eu pensei em algo como, self.performSegue("back")....mas isso parece ser uma má idéia.

Qual é a maneira correta de fazer isso?

cristão
fonte
13
self.navigationController .popViewControllerAnimated (true)?
Kalpesh

Respostas:

526

Swift 3:

Se você deseja voltar ao controlador de exibição anterior

_ = navigationController?.popViewController(animated: true)

Se você deseja voltar ao controlador de visualização raiz

_ = navigationController?.popToRootViewController(animated: true)
Praveen Gowda IV
fonte
1
Como posso enviar dados de volta para o Controlador anterior quando a célula é tocada? se estamos usando o navigationController .popViewControllerAnimated (true)?
JDDelgado
4
@JDDelgado É assim que você envia os dados de volta com o usuário, stackoverflow.com/questions/12561735/…
Mohamad Kaakati: 18/10/2015
36
Para Swift 3 é.popViewController(animated: true)
Sasho 5/16
9
Para calar os avisos:_ = self.navigationController?.popToRootViewController(animated: true)
Andrew K
1
Estamos ignorando o valor de retorno; _ = é a convenção rápida para isso.
Andrew K
53

Swift 3 , Swift 4

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

navigationController é opcional porque pode não haver um.

Vyacheslav
fonte
@Vyacheslva eu estou recebendo um erro "uso implícito de 'seft' no fechamento, use 'auto' para fazer a semântica de captura explícita"
Sandip Subedi
@SandipSubedi use [weak self]eself?.navigationController?.
Vyacheslav
isso foi útil, mas eu quero enviar algumas variáveis com navegação Mas agora eu não posso - eu usei override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let vc = segue.destination as? Mas quando eu uso isso eu não posso usar isso
Saeed Rahmatolahi
como adicionar navigationController então?
USER25
@ user25 add? O que você quer dizer?
Vyacheslav
37

Swift 3

Talvez eu esteja atrasado na resposta, mas no Swift 3 você pode fazer o seguinte:

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)
}
Potência total
fonte
3
Isso não é 'totalmente' correto. Se você apresentar um controlador de exibição que contenha sua própria navegação, e depois de pressionar um controlador de exibição, use esse método dismiss:não apenas descartará o controlador de exibição atual, mas também o controlador de exibição raiz, e não foi o que foi solicitado aqui.
Ernesto Fernandez
2
A pergunta não perguntou se o usuário tinha um controlador de navegação. Esta é a resposta mais simples e melhor para nenhum controlador de navegação. Esta deve realmente ser a resposta aceita.
Droid Chris
Obrigado Droid - Olá ernestofndz, você pode estar certo ao dizer que o rootVC também será descartado, mas isso não acontece comigo, apenas ignora o currentVC, estou adicionando e removendo itens programaticamente e pode não ser a mesma abordagem com os elementos normais de adição no storyboard .. corrija meu entendimento se estiver errado ... para a tabelaVer se o usuário precisa passar detalhes para outra Visualização, esse é outro caso e não tem ligação com o que eu publiquei e concordarei 100% com you..what eu entendi foi que um botão Voltar é necessária neste caso :)
Fullpower
talvez u pode adicionar um pouco introdução .. porque existem descartar & navigationController .popViewController?
marlonpya
dismiss(animated: true, completion: nil)não funciona após a rotação!
user924
31

Swift 4

existem duas maneiras de retornar / voltar ao ViewController anterior:

  1. Primeiro caso : se você usou: self.navigationController?.pushViewController(yourViewController, animated: true) neste caso, você precisa usarself.navigationController?.popViewController(animated: true)
  2. Segundo caso : se você usou: self.present(yourViewController, animated: true, completion: nil) neste caso, você precisa usarself.dismiss(animated: true, completion: nil)

No primeiro caso, verifique se você incorporou o seu ViewController a um navigationController no seu storyboard

Braham Youssef
fonte
19

No caso em que você apresentou um UIViewControllerde dentro de um UIViewControllerie ..

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

Simplesmente chame a dismissfunção:

// Other View Controller
self.dismiss(animated: true)
spencer.sm
fonte
self.dismiss(animated: true)- não funciona após rotação
user924
17

rápido 5 e acima

caso 1: usando com o controlador de navegação

self.navigationController?.popViewController(animated: true)

caso 2: usando com o controlador de exibição atual

self.dismiss(animated: true, completion: nil)
midhun p
fonte
11

Se Segue for 'Show' ou 'Push', você poderá chamar "popViewController (animated: Bool)" na instância de UINavigationController. Ou se segue é uma espécie de "presente", em seguida, chame "dispensar (animado: Bool, conclusão: (() -> Vazio)?)") Com a instância do UIViewController

Pankaj
fonte
7

para o swift 3, você só precisa escrever a seguinte linha de código

_ = navigationController?.popViewController(animated: true)
Amr Angry
fonte
2

Experimente o seguinte: para a visualização anterior, use o seguinte:

navigationController?.popViewController(animated: true)  

pop to root use este código:

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

Swift 4.0 Xcode 10.0 com um TabViewController como última visualização

Se o seu último ViewController estiver incorporado em um TabViewController, o código abaixo o enviará para a raiz ...

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

Mas se você realmente deseja voltar para a última visualização (pode ser a visualização Tab1, Tab2 ou Tab3 ..), é necessário escrever o código abaixo:

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

Isso funciona para mim, eu estava usando uma exibição depois de um dos meus TabView :)

Gabo MC
fonte
1

Para perguntas sobre como incorporar o seu viewController a um navigationController no storyboard:

  1. Abra seu storyboard onde estão localizados os diferentes controladores de exibição
  2. Toque no viewController em que você deseja que seu controlador de navegação inicie
  3. Na parte superior do Xcode, toque em "Editor"
  4. -> Toque em incorporar
  5. -> Toque em "Navegador
Manveer Singh Pandher
fonte
1

Este funciona para mim (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
fonte
0

Eu fiz assim

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
fonte
0

Eu gostaria de sugerir outra abordagem para esse problema. Em vez de usar o controlador de navegação para exibir um controlador de exibição, use o desenrolar segues. Esta solução tem algumas, mas realmente importantes, vantagens:

  1. O controlador de origem pode voltar para qualquer outro controlador de destino (não apenas o anterior) sem saber nada sobre o destino.
  2. As sequências push e pop são definidas no storyboard, portanto, nenhum código de navegação nos controladores de exibição.

Você pode encontrar mais detalhes em Desbobrar segmentos passo a passo . O how to é melhor explicado no link anterior, incluindo como enviar dados de volta, mas aqui farei uma breve explicação.

1) Vá para o controlador de exibição de destino (não a origem) e adicione um segue para descontrair:

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

2) CTRL arraste do próprio controlador de exibição para o ícone de saída no controlador de exibição de origem:

Descontrair do controlador de exibição

3) Selecione a função de desenrolar que você acabou de criar alguns momentos atrás:

Selecionar função de desenrolar

4) Selecione os passos de desenrolamento e dê um nome:

Nomear desenrolar segue

5) Vá para qualquer local do controlador de exibição de origem e chame o seguinte para descontrair:

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

Descobri bastante essa abordagem quando sua navegação começa a ficar complicada.

Espero que isso ajude alguém.

XME
fonte
-3

Posso redirecionar para a página raiz escrevendo código em "viewDidDisappear" do controlador navegado,

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

Mahe
fonte
Isso faz com que o controlador de navegação apareça na raiz, mesmo se você quiser avançar na hierarquia.
bkSwifty