Swift: prepareForSegue с контроллером навигации

Я разрабатываю приложение iOS в Swift.

Я хочу отправить данные из представления другому, используя функцию prepareForSegue.

Однако моему целевому представлению предшествует контроллер навигации, поэтому он не работает.

Как я могу это сделать?

Ответ 1

В prepareForSegue получите доступ к целевому навигационному контроллеру, а затем к его вершине:

let destinationNavigationController = segue.destination as! UINavigationController
let targetController = destinationNavigationController.topViewController

Из целевого контроллера вы можете получить доступ к его представлению и передать данные.

В старых - ныне устаревших - версиях Swift и UIKit код немного отличался:

let destinationNavigationController = segue.destinationViewController as UINavigationController
let targetController = destinationNavigationController.topViewController

Ответ 2

  1. Подготовьте переход в SendViewController

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "segueShowNavigation" {
            if let destVC = segue.destination as? UINavigationController,
                let targetController = destVC.topViewController as? ReceiveViewController {
                targetController.data = "hello from ReceiveVC !"
            }
        }
    }
    
  2. Измените идентификатор, чтобы перейти к "showNavigationController"

screenshot

  1. В свой ReceiveViewController добавьте

это

var data : String = ""

override func viewDidLoad() {
    super.viewDidLoad()
    print("data from ReceiveViewController is \(data)")
}

Конечно, вы можете отправлять любые другие типы данных (int, Bool, JSON...)

Ответ 3

Полный ответ, используя optional binding и Swift 3 & 4:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let navigationVC = segue.destination as? UINavigationController, let myViewController = navigationVC.topViewController as? MyViewControllerClass {
        myViewController.yourProperty = myProperty
    }
}

Ответ 4

Вот ответ для Swift 3:

let svc = segue.destination as? UINavigationController

let controller: MyController = svc?.topViewController as! MyController
controller.myProperty = "Hi there"

Ответ 5

Один вкладыш в Swift 3:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  if let vc = segue.destination.childViewControllers[0] as? FooController {
    vc.variable = localvariable
  }
}

Ответ 6

В Swift 5

Если вам необходимо не только перейти от SourceViewController к DestinationViewController, встроенному в UINavigationController, но также и к новой раскадровке, выполните следующие действия...

  1. Поместите объект "Storyboard Reference" из библиотеки объектов рядом с исходным ViewController в Interface Builder, а затем перетащите переход к нему (например, с помощью кнопки в представлении SourceViewController). Например, назовите идентификатор segue "ToOtherStoryboard".

  2. Перейдите в NavigationViewController и присвойте ему идентификатор раскадровки с помощью инспектора идентификации. "DestinationNavVC" будет делать.

  3. Щелкните по значку Storyboard Reference, который вы создали на шаге 1, и в его поле "Инспектор атрибутов" введите идентификатор Storyboard ID, который вы написали для UINavigationController на шаге 2. Это создаст переход от источника к DestinationViewController независимо от того, что вы пишете в Исходный файл исходного ViewController. Это связано с тем, что при переходе к NaviationController автоматически отображается корневой ViewController (первый) UINavigationController.

  4. (НЕОБЯЗАТЕЛЬНО) Если вам необходимо прикрепить данные вместе с segue и отправить их в свойства в DestinationViewController, вы должны написать следующий код в методе Prepare-For-Segue в файле SourceViewController:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "ToOtherStoryboard" {
            let destinationNavVC = segue.destination as! UINavigationController
            let destinationVC = destinationNavVC.topController as!     DestinationViewController
    
            destinationVC.name = nameTextField.text // for example
            destinationVC.occupation = occupationTextField.text
        }
    }
    

    Вам НЕ НУЖНО иметь PrepareForSegue, если вы просто пытаетесь перейти от одного ViewController к другому, описанные выше методы будут работать (без шага 3)

  5. В вашем методе IBAction Outlet для кнопки, которую вы использовали для инициации перехода, вы должны написать:

    performSegue(withIdentifer: "ToOtherStoryboard", sender: self)