I have a UITableView which I have set up to go to a different VC when a row is selected by the user (the table only consists of one array). I want to pass the row index of the selected item. I am using didSelectRowAtIndexPath to set a variable named selectedCellIndex to the row index. However, since I also have the tableView set up to go to the next VC prepareForSegue fires off (or around the same time) as didSelectRowAtIndexPath. As a result the first time I select an item from the list the value sent is nil, after that I always get the previous value of the row selected. Any Ideas on how to make sure that the variable is set before the app transitions to the next segue without putting a pause?
Here is my code:
var selectedCellIndex:Int!
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
var indexPath = tableView.indexPathForSelectedRow() as NSIndexPath?
selectedCellIndex = indexPath?.row as Int?
}
//SEGUE
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "signature" {
let vc = segue.destinationViewController as SignatureViewController
vc.index = "\(selectedCellIndex)"
}
}
Thanks
You can get the selected index path from the table view directly using the indexPathForSelectedRow method. There is no need to implement didSelectRowAtIndexPath just to store the selected index.
The prepareForSegue: method is the only method where you should set/access variables that are necessary for a transition.
Related
I have a set up that transfers info (the index for the cell selected) in a tableViewController so that the destination UIViewController can display some text info on a label by calling the appropriate index from an array. This all works correctly. However, there are 3 sections and I want the destination UIViewController to know which section was selected. (Ie. selecting the first cell in section 1 and the first cell in section 2 both return an index of 0, but I need it to be differentiable). I thought of passing the value of the selected section (and then setting up an if/else statement in the destination UIViewController) but I am not sure how to do that appropriately.
Here is the current code I have for the non-differentiating index pass:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let indexPath = self.tableView.indexPathForSelectedRow
let rowSelectedd = indexPath?.row
let destViewController: Controller = segue.destination as! Controller
destViewController.rowSelected = rowSelectedd!
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "rowSelected", sender: rowSelectedd)
}
Basically, how do I pass the value of the section of the selected cell?
If the destination controller needs both the row and section of the selected row, then use an IndexPath property instead of an Int property and pass the whole indexPath instead of just indexPath.row.
But why does the destination controller need to know the index path? That makes no sense. Why not pass the actual data for that index path (from your data model) to the destination controller?
I have a table view with a list of events. I now am trying to create a dynamic view that can show details about all of those events based on the event tapped on. Two questions I have are how do I create a generic segue that I can use for any table cell to go to the same view, and then in that view how do I access the cell that brought the user to the view?
You would use didSelectRowAtIndexPath. First, create a variable eventToPass of type Event (or whatever your class is called) on your ViewController. Then, you should get the object that represents your data, then pass that to your new UIViewController. Something like:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let event = eventsArray[indexPath.row]
self.eventToPass = event
self.performSegueWithIdentifier("EventSegue", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "EventSegue") {
var detailVC = segue.destinationViewController as EventDetailViewController
detailVC.event = eventToPass
}
}
This assumes that you have a ViewController called EventDetailViewController that has a property called event. From here, you can access any of the event's details on your new ViewController.
In my first table view I have an array which populates the table view. The user then clicks a cell. Each cell has a different text label. I want to carry the label value from one table view to the next, but when it gets to the other table view the variable I try to set it to is nil. I am using segues and have tried to use prepareForSeguge function. I just can't get the variable to save once it's left the didSelectRowatIndexPath method.
EDIT: I used an observer to check that my variable was being set, but it isn't set until after all other functions have run. How Would I then be able to use my variable in my second tableview to populate the table?
Here is my code:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Get Cell Label
let indexPath = tableView.indexPathForSelectedRow;
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;
GenreSelector = currentCell.textLabel!.text
print(GenreSelector)
performSegueWithIdentifier("letsGo", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "letsGo") {
// initialize new view controller and cast it as your view controller
let viewController = segue.destinationViewController as! ResultTableViewController
// your new view controller should have property that will store passed value
viewController.GenreSelection = GenreSelector
}
}
I need to pass a variable containing the index of the selected row in one view to the next view.
firstview.swift
var selectedRow = 0;
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRow = indexPath.row + 1
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "viewAssignmentsSegue") {
let navController = segue.destinationViewController as! UINavigationController
let controller = navController.viewControllers[0] as! AssignmentsViewController
print(selectedRow)
controller.activeCourse = selectedRow
}
}
My issue is that, when a row is selected, the selectedRow variable isn't updated by the tableView method before the segue occurs, meaning that the value is essentially always one behind what it should be. How can I delay the prepareForSegue until the variable is updated or how else can I successfully pass the selected row to the next view without delay?
One possibility: Don't implement didSelectRowAtIndexPath:. Just move that functionality into your prepareForSegue implementation. That, after all, is what is called first in response to your tapping the cell. Even in prepareForSegue you can ask the table view what row is selected.
Another possibility: Implement willSelectRowAtIndexPath: instead of didSelectRowAtIndexPath:. It happens earlier.
in your prepareForSegue:
controller.activeCourse = self.tableView.indexPathForSelectedRow
don't wait for didSelect to be called - react earlier.
Use this on prepareForSegue:
let path = self.tableView.indexPathForSelectedRow()!
controller.activeCourse = path.row
or
let path = self.tableView.indexPathForCell(sender)
controller.activeCourse = path.row
I am trying to figure how to segue to a new view when the user selects a certain row in the current tableview. I am thinking this will be done by the didselectrowatindexpath method but can not figure out the logic of how it will work. I would like it to display a view with the specific courses in the subject the user selected. I think this will use an array? I would appreciate any help here thanks.
Yes, you're right, you can do this be responding to didSelectRowAtIndexPath.
You can have a view controller as your table view delegate that implements these methods:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
if let thing = self.things.objectAtIndex(indexPath.row) as? Thing
{
self.performSegueWithIdentifier("OpenThing", sender: thing)
}
}
Where "OpenThing" is a segue defined in my storyboard.
Then I have overridden the prepareForSegue method:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "OpenThing"
{
if let controller = segue.destinationViewController as? ThingViewController
{
if let thing = sender as? Thing
{
controller.thing = thing
}
}
}
}
This is a contrived example of having an array of "Things". I access a thing by row index then segue to the next view controller, providing the thing that I want to display.