使用导航控制器在`prepareForSegue`中设置数据

78

我正在使用Swift开发iOS应用程序。

我想使用 prepareForSegue 函数将数据从一个视图发送到另一个视图。

然而,我的目标视图之前有一个导航控制器,所以它不起作用。 我如何在导航控制器中包含的VC上设置数据?

8个回答

144

prepareForSegue 中访问目标导航控制器,然后访问其顶部:

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

通过目标控制器,您可以访问其视图并传递数据。

在旧版本的Swift和UIKit中(现在已过时),代码略有不同:

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

使用了这段代码,但是在targetController中使用dot something时,我无法访问到secondViewController中的变量receivedTest - biggreentree
9
很可能你需要将 destinationNavigationController.topViewController 强制转换为 secondViewController 类型。 - Wojtek Surowka

33
  1. 在SendViewController中准备segue。

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 !"
        }
    }
}
  • 将标识符segue编辑为“showNavigationController”

  • screenshot

    1. 在您的ReceiveViewController中添加

    this

    var data : String = ""
    
    override func viewDidLoad() {
        super.viewDidLoad()
        print("data from ReceiveViewController is \(data)")
    }
    
    当然,您可以发送任何其他类型的数据(int、Bool、JSON等)。

    17

    使用 可选绑定 和 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代码:

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

    4

    这里是Swift 3的答案:

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

    2

    在Swift 5中

    如果您不仅需要从SourceViewController到嵌入在UINavigationController中的DestinationViewController进行segue,还需要到一个新的Storyboard中,那么请按照以下步骤操作...

    最初的回答:

    1. Place a "Storyboard Reference" object from your Object Library next to your source ViewController in Interface Builder, and then drag a segue to it (from a button on the SourceViewController view, for instance). Name the segue identifier "ToOtherStoryboard", for example.

    2. Go to NavigationViewController and give it a Storyboard ID using the Identity Inspector. "DestinationNavVC" would do.

    3. Click the Storyboard Reference icon you created in step 1, and in its attribute inspector's 'Referenced ID' field, enter the Storyboard ID you wrote for the UINavigationController in step 2. This creates the segue from source to the DestinationViewController no matter what you write in source file of the source ViewController. This is because seguing to a NaviationController will automatically show the root ViewController (the first one) of the UINavigationController.

    4. (OPTIONAL) If you need to attach data along with your segue and send it to properties within the DestinationViewController, you would write the following code inside a Prepare-For-Segue method in your SourceViewController file:

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

      You do not NEED to have a PrepareForSegue if you're simply trying to move from one ViewController to another, the methods above will work (w/o step 3)

    5. In your IBAction Outlet method for your button you used to initiate the segue, you would write:

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

    代码编辑器(控制键K)无法处理以“override”开头的代码段,可能是因为其中一行代码太长了? - John Pitts

    1

    在segue箭头属性中设置标识符名称,以便在performeSegue中使用。

    就像这样:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    
        if let vc: ProfileViewController = segue.destination as? ProfileViewController {
    
            //do any setting to the next screen
    
        }
    
    }
    

    然后:
        performSegue(withIdentifier: "yourIdentifierOfViewProfile", sender: indexPath.row)
    

    我希望它有所帮助。

    1

    跳过对 UINavigationController 的检查是一个好主意,因为可能有多个 segues 使用一个 navigationController,所以每个使用 navigationControllersegue 都会进入该检查。更好的方法是检查第一个 childrenviewController 并将其转换为您要查找的 viewController

    if let destVC = segue.destination.children.first as? MyViewController {
        destVC.hideBottomBar = true
    }
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接