Set data in `prepareForSegue` with navigation controller

IosSwiftUinavigationcontroller

Ios Problem Overview


I am developing an iOS application in Swift.

I want to send data from a view to an other one, using the prepareForSegue function.

However, my target view is preceded by a navigation controller, so it doesn't work. How can I set data on the VC contained within the navigation controller?

Ios Solutions


Solution 1 - Ios

In prepareForSegue access the target navigation controller, and then its top:

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

From the target controller you can access its view and pass data.

In old - now obsolete - versions of Swift and UIKit the code was slightly different:

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

Solution 2 - Ios

  1. Prepare the segue in the 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. Edit the identifier segue to "showNavigationController"

screenshot

  1. In your ReceiveViewController add

this

var data : String = ""

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

Of course you can send any other type of data (int, Bool, JSON ...)

Solution 3 - Ios

Complete answer using optional binding and 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
    }
}

Solution 4 - Ios

Here is the answer for Swift 3:

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

Solution 5 - Ios

A one liner in Swift 3:

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

Solution 6 - Ios

In Swift 5

If you must not only segue from a SourceViewController to a DestinationViewController embedded in a UINavigationController, but also to a new Storyboard also, then do the following...

  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)

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

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

Solution 7 - Ios

Set the identifier name in the segue arrow property in order to use in the the performeSegue.

Like this:

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

and then:

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

I hope it helps.

Solution 8 - Ios

It's a good idea to skip the check for UINavigationController as there may be multiple segues that use a navigationController and so will go into that check for every segue that uses a navigationController. A better way is to check the first viewController of the children and cast it as the viewController you are looking for.

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questioncedric petetinView Question on Stackoverflow
Solution 1 - IosWojtek SurowkaView Answer on Stackoverflow
Solution 2 - IosmattyUView Answer on Stackoverflow
Solution 3 - Iosjason zView Answer on Stackoverflow
Solution 4 - IosOndrej KvasnovskyView Answer on Stackoverflow
Solution 5 - IosJoeGalindView Answer on Stackoverflow
Solution 6 - IosJohn PittsView Answer on Stackoverflow
Solution 7 - IosAlan SilvaView Answer on Stackoverflow
Solution 8 - IosJoakim SjöstedtView Answer on Stackoverflow