71

One of my segues transitions from a view controller to a tableview controller. I want to pass an array between the two, but with a navigation controller before the tableview controller, I can't figure out how to pass the array. How do you pass data through a navigatiom controller to a tableview controller?

Tommy Devoy
  • 13,441
  • 3
  • 48
  • 75
user3142972
  • 897
  • 1
  • 8
  • 11

8 Answers8

136

Override prepareForSegue and set whatever value on the tableview you'd like. You can grab the tableview from the UINavigation viewControllers property.

override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!){

   let navVC = segue.destinationViewController as UINavigationController

   let tableVC = navVC.viewControllers.first as YourTableViewControllerClass

   tableVC.yourTableViewArray = localArrayValue   
}

For Swift 3 :

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

   let navVC = segue.destination as? UINavigationController

   let tableVC = navVC?.viewControllers.first as! YourTableViewControllerClass

   tableVC.yourTableViewArray = localArrayValue   
}
Mamta
  • 921
  • 1
  • 10
  • 28
Tommy Devoy
  • 13,441
  • 3
  • 48
  • 75
24

@Tommy Devoy's answer is correct but here is the same thing in swift 3

Updated Swift 3

  // MARK: - Navigation

//In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.


    if segue.identifier == "yourSegueIdentifier"  {

        if let navController = segue.destination as? UINavigationController {

            if let chidVC = navController.topViewController as? YourViewController {
                 //TODO: access here chid VC  like childVC.yourTableViewArray = localArrayValue 


            }

        }

    }

}
Indrajit Sinh Rayjada
  • 1,243
  • 1
  • 14
  • 24
12

I was getting this error to Horatio's solution.

ERROR: Value of type 'UINavigationController' has no member 'yourTableViewArray'

So this might help others like me looking for a code only solution. I wanted to redirect to a Navigation controller, yet pass data to root view controller within that Nav Controller.

if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "yourNavigationControllerID") as? UINavigationController,
   let yourViewController = controller.viewControllers.first as? YourViewController {
        yourViewController.yourVariableName = "value"
        self.window?.rootViewController = controller  // if presented from AppDelegate
        // present(controller, animated: true, completion: nil) // if presented from ViewController
}
mythicalcoder
  • 3,143
  • 1
  • 32
  • 42
  • 1
    Perfecto solution, just to clarify, if presenting from AppDelegate, use self.window?.... and leave // present commented, if presenting from ViewController, comment // self.window?... and uncomment present(controller – Alejandro Luengo Jun 25 '17 at 17:53
  • 1
    yes, because present() requires ViewController. Isn't it! But it has been some time since I am in touch with this. You can confirm by actually testing it out and probably leave a comment or suggest edit for the answer. I will update surely. – mythicalcoder Jun 25 '17 at 18:04
  • 1
    Yes, it's ok, self.window?.rootViewController = controller if presented from AppDelegate and present(controller, animated: true, completion: nil) if presented from ViewController, just choose your case and comment the other one – Alejandro Luengo Jul 17 '17 at 11:34
12

SWIFT 3 (tested solution) - Passing data between VC - Segue with NavigationController

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        let navigationContoller = segue.destination as! UINavigationController

        let receiverViewController = navigationContoller?.topViewController as ReceiverViewController

        receiverViewController.reveivedObject = sentObject 
    }
LamaTo
  • 540
  • 1
  • 8
  • 21
8

Tommy's solution requires you to set up the Segue in Storyboard.

Here is a code only solution:

func functionToPassAsAction() {
    var controller: UINavigationController
    controller = self.storyboard?.instantiateViewControllerWithIdentifier("NavigationVCIdentifierFromStoryboard") as! UINavigationController 
    controller.yourTableViewArray = localArrayValue
    self.presentViewController(controller, animated: true, completion: nil)
}
Bista
  • 7,869
  • 3
  • 27
  • 55
Horatio
  • 1,695
  • 1
  • 18
  • 27
5

Swift 5

class MyNavigationController: UINavigationController {
    
    var myData: String!
    
    override func viewDidLoad() {
        if let vc = self.topViewController as? MyViewcontoller{
            vc.data = self.myData
        }
    }
    
}

   let navigation = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "MyNavigationController") as! MyNavigationController
   navigation.myData = "Data that you want to pass"
   present(navigation, animated: true, completion: nil)
Rashid Latif
  • 2,809
  • 22
  • 26
  • 1
    the best solution for a code-only approach. didn't even know the `topViewController` property existed on a `navigation controller` – colin May 03 '21 at 07:12
3

FIXED syntax for SWIFT 3

  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let navVC = segue.destination as! UINavigationController
        let tableVC = navVC.viewControllers.first as! YourTableViewControllerClass

        tableVC.yourTableViewArray = localArrayValue
    }
MANISH PATHAK
  • 2,602
  • 4
  • 27
  • 31
0

passing a text in tableview swift 4 **or just pass data but change the function **

First View Controller

class

 let name_array = ["BILL GATES", "MARK ZUKERBERG", "DULKAR SALMAN", "TOVINO" , "SMITH"]

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){

    let story: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)

    let new = story.instantiateViewController(withIdentifier: "SecondViewController")as! SecondViewController

        new.str1 = name_array[indexPath.row]

    self.navigationController?.pushViewController(new, animated: true)

Second View Controller

class SecondViewController: UIViewController {

@IBOutlet weak var lbl2: UILabel!

var str1 = String()

override func viewDidLoad() {
    super.viewDidLoad()

     lbl2.text =  str1

}