Sending data to a new view controller through didselectrowatindexpath

Dan Levy Source

I have a tableview set up in one view controller and I am trying to send the indexPath.row text to a new view controller's label. I am getting an error that says it found nil when unwrapping an optional value. If I print "selectedClass" in the viewController code shown below, I get the text of indexPath.row. If I print the text in the new viewController, I get nothing. Here is my code:


override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    let classIndexPath = tableView.indexPathForSelectedRow!

    let selectedCell = tableView.cellForRowAtIndexPath(classIndexPath)! as UITableViewCell


    let spinningActivity = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
    spinningActivity.labelText = "Just a Moment"

    if reachabilityStatus == kNOTREACHABLE {

        spinningActivity.hide(true)

        self.displayAlert("No Internet Connection", message: "Please connect to the internet before continuing.")


    } else {

        spinningActivity.hide(true)

        let selectedClass = selectedCell.textLabel!.text!

        let newCardSetVC = self.storyboard?.instantiateViewControllerWithIdentifier("NewCardSetViewController") as! NewCardSetViewController

        newCardSetVC.selectedClassLabel.text = selectedClass as String



        self.performSegueWithIdentifier("addCardSetSegue", sender: self)


    }

}

swift

Answers

answered 2 years ago boidkan #1

Try something like this:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    let classIndexPath = tableView.indexPathForSelectedRow!
    let selectedCell = tableView.cellForRowAtIndexPath(classIndexPath)! as UITableViewCell
    let spinningActivity = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
    spinningActivity.labelText = "Just a Moment"
    if reachabilityStatus == kNOTREACHABLE {
        spinningActivity.hide(true)
        self.displayAlert("No Internet Connection", message: "Please connect to the internet before continuing.")

    } else {
        spinningActivity.hide(true)
        self.performSegueWithIdentifier("addCardSetSegue", sender: self)
    }
}


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "addCardSetSegue"{
        if let indexPath = tableView!.indexPathForSelectedRow as NSIndexPath?{
             let selectedCell = tableView?.cellForRowAtIndexPath(indexPath)
             let selectedClass = selectedCell.textLabel!.text!
             let vc = segue.destinationViewController as! NewCardSetViewController
             vc.selectedClassLabel.text = selectedClass as String
        }
    }
}

So when you performSegueWithIdentifier you are creating a instance if that VC and not using the instance you created in didSelectRowAtIndexPath. So the solution is to instead use the instance created by performSegue. Which is done by calling segue.destinationViewController in prepareForSegue.

An alternate solutions could be not calling performSegueWithIdentifier and instead calling something like self.presentViewController(newCardSetVC, animated: true, completion: nil) instead as I stated in the comments.

Hope this helps, let me know if you have any questions.

answered 2 years ago MikeG #2

Perhaps something like this ...

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

    if segue.identifier == "segID" {

    let navigationController = segue.destinationViewController as! UINavigationController
    let controller = navigationController.topViewController as! NewCardSetViewController
    let selectedCell = tableView.cellForRowAtIndexPath(indexPathForSelectedRow)! as UITableViewCell
    let selectedClass = selectedCell.textLabel!.text!
    newCardSetVC.selectedClassLabel.text = selectedClass as String
        }
  }

and you can use
self.performSegueWithIdentifier("addCardSetSegue", sender: self)

in your didSelectRowAtindexPath

if your NewCardSetViewController is not embedded in a nav controller you can skip one of the lines above and go straight to it with...

let controller = segue.destinationViewController as! NewCardSetViewController

answered 2 years ago Hitendra Hckr #3

You are trying to set string value in label of NewCardSetViewController.

NewCardSetViewController will only load in memory after perform segue. So, viewDidLoad() of NewCardSetViewController will call after segue.

In your code you are trying to set value before segue perform. To passData in nextViewController you need to create variable with same dataType of data your are trying to pass.

In your case create string variable in NewCardSetViewController say strSelectedClass, instead of setting value directly to label, set value of that variable i.e. strSelectedClass.

Replace line

newCardSetVC.selectedClassLabel.text = selectedClass as String

with

newCardSetVC.strSelectedClass = selectedClass as String

In viewDidLoad: of NewCardSetViewController put below line, it will display value onto your label.

self.selectedClassLabel.text = self.strSelectedClass

you have created object, so all variable of NewCardSetViewController will get memory, but IBOutlet will not.

IBOutlet will only get memory after segue perform or pushViewController.

comments powered by Disqus