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?


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)

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.


@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)
}

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


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)

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)

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


7

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

_ = navigationController?.popViewController(animated: true)

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) 

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 :)


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

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")
        }
      }
    }
}

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)
}

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.


-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) }


Isso faz com que o controlador de navegação apareça na raiz, mesmo se você quiser avançar na hierarquia.
bkSwifty
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.