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

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

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

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

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

16 ответов

Решение

Свифт 3:

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

_ = navigationController?.popViewController(animated: true)

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

_ = navigationController?.popToRootViewController(animated: true)

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

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

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

Свифт 5 и выше

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

self.navigationController?.popViewController(animated: true)

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

self.dismiss(animated: true, completion: nil)

Свифт 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)
}

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 в навигационный контроллер в вашей раскадровке

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

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

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

// Other View Controller
self.dismiss(animated: true)

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

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

_ = navigationController?.popViewController(animated: true)

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

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

navigationController?.popViewController(animated: true)  

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

navigationController?.popToRootViewController(animated: true) 

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

  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) Перейдите в любое место исходного контроллера представления и вызовите переход:

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

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

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

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

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

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

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

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

Если вы хотите закрыть предыдущие два контроллера представления, просто вызовите popViewController два раза следующим образом:

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

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

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

Другие вопросы по тегам