Программно вернуться к предыдущему ViewController в Swift

211

Я отправляю пользователя на страницу одним нажатием кнопки. Эта страница является UITableViewController .

Теперь, если пользователь нажимает на ячейку, я бы хотел вернуть его на предыдущую страницу.

Я думал о чем-то вроде, self.performSegue("back")....но это, кажется, плохая идея.

Как правильно это сделать?

Кристиан
источник
13
self.navigationController? .popViewControllerAnimated (true)
Kalpesh

Ответы:

527

Свифт 3:

Если вы хотите вернуться к предыдущему виду контроллера

_ = navigationController?.popViewController(animated: true)

Если вы хотите вернуться к корневому контроллеру представления

_ = navigationController?.popToRootViewController(animated: true)
Правин Говда IV
источник
1
Как я могу отправить данные обратно в предыдущий контроллер, когда ячейка коснулась? если мы используем навигационный контроллер? .popViewControllerAnimated (true)
JDDelgado
4
@JDDelgado Вот как вы отправляете данные обратно пользователю, stackoverflow.com/questions/12561735/…
Мохамад Каакати
36
Для Swift 3 это.popViewController(animated: true)
Sasho
9
Чтобы скрыть любые предупреждения:_ = self.navigationController?.popToRootViewController(animated: true)
Андрей K
1
Мы игнорируем возвращаемое значение; _ = это быстрое соглашение для этого.
Андрей К
53

Свифт 3 , Свифт 4

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

navigationController является необязательным, поскольку его может не быть.

Вячеслав
источник
@Vyacheslva Я получаю сообщение об ошибке «неявное использование« seft »при закрытии, используйте« self », чтобы сделать семантику захвата явной»
Sandip Subedi
@SandipSubedi использовать [weak self]иself?.navigationController?.
Вячеслав
это было полезно , но я хочу , чтобы отправить некоторые переменные с навигацией Но теперь я не могу - я override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let vc = segue.destination as? Но когда я использую это я не могу использовать что
Саида Rahmatolahi
как добавить navigationController тогда?
user25
@ user25 добавить? что вы имеете в виду?
Вячеслав
37

Свифт 3

Я мог бы опоздать с ответом, но для быстрого 3 вы можете сделать это следующим образом:

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
Это не «полностью» правильно. Если вы представляете контроллер представления, который содержит свою собственную навигацию, и после того, как вы нажимаете контроллер представления, используйте этот метод, dismiss:он не только отклонит текущий контроллер представления, но и корневой контроллер представления, и это не то, что было задано здесь.
Эрнесто Фернандес
2
Вопрос не задавался, был ли у пользователя навигационный контроллер. Это самый простой и лучший ответ для не навигационного контроллера. Это действительно должен быть принятый ответ.
Дроид Крис
Спасибо Droid - Привет, ernestofndz, возможно, вы правы, говоря, что rootVC также будет удален, но со мной этого не происходит, он только отклоняет currentVC, я добавляю и удаляю элементы программно, и это может быть не тот подход с обычным добавлением элементов на раскадровку ... исправьте мое понимание, если я ошибаюсь ... для tableView, если пользователю нужно передать детали в другое представление, тогда это другой случай, и он не связан с тем, что я опубликовал, и согласен на 100% с вами .. что я понял, так это то, что в этом случае требуется кнопка «Назад» :)
Fullpower
может быть, вы можете добавить небольшое введение .. потому что существуют dismiss & navigationController? .popViewController
marlonpya
dismiss(animated: true, completion: nil)не работает после вращения!
user924
32

Swift 4

есть два способа вернуться / вернуться к предыдущему ViewController:

  1. Первый случай : если вы использовали: self.navigationController?.pushViewController(yourViewController, animated: true) в этом случае вам нужно использоватьself.navigationController?.popViewController(animated: true)
  2. Второй случай : если вы использовали: self.present(yourViewController, animated: true, completion: nil) в этом случае вам нужно использоватьself.dismiss(animated: true, completion: nil)

В первом случае убедитесь, что вы встроили свой ViewController в navigationController в вашей раскадровке

Брахам Юсеф
источник
19

В случае, когда вы представили UIViewControllerизнутри то UIViewControllerесть ..

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

Просто вызовите dismissфункцию:

// Other View Controller
self.dismiss(animated: true)
spencer.sm
источник
self.dismiss(animated: true)- не работает после ротации
user924
17

Свифт 5 и выше

вариант 1: использование с контроллером навигации

self.navigationController?.popViewController(animated: true)

Случай 2: использование с настоящим контроллером представления

self.dismiss(animated: true, completion: nil)
мидхун р
источник
11

Если Segue является видом 'Show' или 'Push', то вы можете вызвать "popViewController (animated: Bool)" в экземпляре UINavigationController. Или, если segue является своего рода «настоящим», тогда вызовите «dismiss (animated: Bool, завершение: (() -> Void)?)» С экземпляром UIViewController

Панкай
источник
7

для Swift 3 вам просто нужно написать следующую строку кода

_ = navigationController?.popViewController(animated: true)
Амр Злой
источник
2

Попробуйте это: для предыдущего просмотра используйте это:

navigationController?.popViewController(animated: true)  

поп в корень используйте этот код:

navigationController?.popToRootViewController(animated: true) 
Ahsan
источник
2

Swift 4.0 Xcode 10.0 с TabViewController в качестве последнего представления

Если ваш последний ViewController встроен в TabViewController, приведенный ниже код отправит вас в корень ...

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

Но если вы действительно хотите вернуться к последнему представлению (это может быть представление Tab1, Tab2 или Tab3 ...), вы должны написать следующий код:

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

Это работает для меня, я использовал представление после одного из моего TabView :)

Габо MC
источник
1

Для вопросов, касающихся того, как встроить ваш viewController в navigationController в раскадровке:

  1. Откройте раскадровку, в которой расположены ваши разные viewController
  2. Нажмите на viewController, с которого вы хотите запустить свой контроллер навигации
  3. В верхней части Xcode нажмите «Редактор»
  4. -> Нажмите встраивать в
  5. -> Нажмите «Контроллер навигации
Манвеер Сингх Пандер
источник
1

Этот работает для меня (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

Я сделал это так

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

Я хотел бы предложить другой подход к этой проблеме. Вместо того, чтобы использовать контроллер навигации, чтобы открыть контроллер представления, используйте разматывать сегменты. Это решение имеет несколько, но действительно важных преимуществ:

  1. Контроллер источника может вернуться к любому другому контроллеру назначения (не только к предыдущему), ничего не зная о пункте назначения.
  2. Сегменты push и pop определены в раскадровке, поэтому в контроллерах представления нет кода навигации.

Вы можете найти более подробную информацию в разделе «Размотка сегментов» . Как лучше объяснить в предыдущей ссылке, в том числе, как отправить данные обратно, но здесь я сделаю краткое объяснение.

1) Перейдите к контроллеру представления пункта назначения (не источника) и добавьте раскрутку:

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

2) Перетащите CTRL от самого контроллера представления к значку выхода в исходном контроллере представления:

Отмотать от просмотра контроллера

3) Выберите функцию размотки, которую вы только что создали несколько минут назад:

Выберите функцию размотки

4) Выберите "раскрутить" и дайте ему имя:

Имена раскручивают

5) Пойдите в любое место контроллера представления источника и вызовите sewind:

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

Я обнаружил, что такой подход приносит много пользы, когда ваша навигация начинает усложняться.

Я надеюсь, что это поможет кому-то.

XME
источник
-3

Я могу перенаправить на корневую страницу, написав код в «viewDidDisappear» контроллера,

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

Маэ
источник
Это приводит к тому, что контроллер навигации попадает в корень, даже если вы хотите двигаться вперед в иерархии.
bkSwifty