4

Using this code I am able to 'segue' to the same instance of my view controller

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: "DetailVC")
    self.navigationController?.pushViewController(vc, animated: true)


}

However, how do I pass data over? I only know how to pass data using the segue option. When I run the code with this, I get nil errors because the new instantiated view controller cannot read the data.

baxu
  • 303
  • 1
  • 4
  • 12

6 Answers6

12

for example I add here, for detail description you can get the tutorial from here

class SecondViewController: UIViewController {

var myStringValue:String?

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
}

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    // We will simply print out the value here
    print("The value of myStringValue is: \(myStringValue!)")
}

and send the string as

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: "DetailVC") as! SecondViewController
      vc.myStringValue = "yourvalue"

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


}
Anbu.Karthik
  • 82,064
  • 23
  • 174
  • 143
6

First off. This isn't a segue. This is just pushing another view to the stack. And (like Ashley Mills says) this is not the same instance you are currently in. This is a NEW instance of a view controller.

But all you need to do is populate the data. You already have the controller here...

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    // you need to cast this next line to the type of VC.
    let vc = storyboard.instantiateViewController(withIdentifier: "DetailVC") as! DetailVC // or whatever it is
    // vc is the controller. Just put the properties in it.
    vc.thePropertyYouWantToSet = theValue

    self.navigationController?.pushViewController(vc, animated: true)
}

Then in your second view controller catch the value like this

class DetailVC: UIViewController {
    var thePropertyYouWantToSet = String()

    override func viewDidLoad() {
        print(thePropertyYouWantToSet)
    }
}
DragonFire
  • 3,722
  • 2
  • 38
  • 51
Fogmeister
  • 76,236
  • 42
  • 207
  • 306
5

What you're using isn't a segue. This is just pushing a NEW instance (not the same one) of view controller onto the nav stack.

To segue, in your storyboard, you can just drag a link from the collection view cell to the view controller, then assign data in the prepareForSegue method…

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let viewController = segue.destinationViewController as? DetailVC {
        viewController.someProperty = self.someProperty
    }
}
Ashley Mills
  • 50,474
  • 16
  • 129
  • 160
  • Chose this answer because, while all the answers are technically correct, this was the only one that showed that I had to use `self.` in order to pass the same values, which was the real issue – baxu Jan 26 '17 at 04:32
2

In DetailVC, Create a variable and assign value while you create an object. Check example below:

class DetailVC {
 var dataString: String?
}

Pass data like below:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: "DetailVC") as! DetailVC
    vc.dataString = "PASS THE DATA LIKE THIS"
    self.navigationController?.pushViewController(vc, animated: true)


}
zeeshan
  • 4,913
  • 1
  • 49
  • 58
Parth Adroja
  • 13,198
  • 5
  • 37
  • 71
1

If you're following the no storyboard pattern you can do it like this

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let viewController = NextViewController()
    viewController.dataInsideNextViewController = "Data to be passed"
    navigationController?.pushViewController(viewController, animated: true)
}
Nico Dioso
  • 195
  • 2
  • 15
0

In your ViewController1 launch your ViewController2 using these code

Class ViewController1: UIViewController {

    var dataFromVC2 = ""

    func loadVC2() {
        let vc2 = ViewController2()
        vc2.dataFromVC1 = "Hi VC2"
        vc2delegate = self
        navigationController?.pushViewController(vc2, animated: true)
    }        

}

In your ViewController2, add this code. You can use the delegate property to pass back data from ViewContoller2.

Class ViewController2: UIViewController {

    var dataFromVC1: String = ""
    weak var delegate: ViewController1!

    func passData_toVC1() {
        delegate.dataFromVC2 = "How's it going VC1?"
    }        

}