Use Didselectrowatindexpath or Prepareforsegue Method for Uitableview

Use didSelectRowAtIndexPath or prepareForSegue method for UITableView?

If you use prepareForSegue:sender:then you won't have as much to change if you later decide to trigger the segue from some control outside the table view.

The prepareForSegue:sender: message is sent to the current view controller, so I'd suggest something like this:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Assume self.view is the table view
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
DetailObject *detail = [self detailForIndexPath:path];
[segue.destinationViewController setDetail:detail];
}

In Swift:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let path = self.tableView.indexPathForSelectedRow()!
segue.destinationViewController.detail = self.detailForIndexPath(path)
}

How can I run prepareForSegue After didSelectRowAtIndexPath?

If you have linked the segue directly from your cell in the storyboard then didSelectRowAtIndexPath will not execute before the segue is triggered.

What you can do is create a segue by Ctrl-dragging from the view controller object in the storyboard to the destination scene and giving the segue an identifier as you would with any other segue. Delete the segue from your cell.

Now you can call performSegueWithIdentifier to trigger the segue and pass the object that was selected as the sender

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// tableView.deselectRowAtIndexPath(indexPath) // Optionally deselect the row for a cleaner appearance
self.performSegueWithIdentifier("mySegueIdentifier", sender: queryArray[indexPath.row])
}

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

if let detailScene = segue.destinationViewController as? ListaTableViewController {
let categoriaEscolhida = sender as! PFObject
detailScene.categoria = categoriaEscolhida.objectForKey("nome") as! String

}
}

Swift didSelectRowAtIndexPath and prepareForSegue

You can fetch the selected indexPaths from tableView in your prepare for segue

    func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "editSegue")
{
if let indexPath = tableView.indexPathForSelectedRow{
let viewController : WorkoutView = segue.destinationViewController as! WorkoutView
viewController.workoutInfoData = marrStudentData.objectAtIndex(indexPath.row) as! WorkoutInfo
navigationItem.title = ""
}
}
}

Should I use didSelectRowAtIndexPath, prepareForSegue, or both?

Call prepareForSegue method inside didSelectRowAtIndexPath method to navigate to secondViewController then to display details, make network call inside viewDidLoad method of secondViewController and show activityIndicatorView until the data is fetched.

To Segue or to didSelectRowAtIndexPath?

You need to use both, in didSelectRowAtIndexPath you should call [self performSegueWithIdentifier:@"identifier" sender:self];

In the same View Controller you should have the prepareForSegue method grab the destinationViewController out of the segue, and then set whatever properties on that view controller that you wish to set.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
self.someProperty = [self.someArray objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:@"segueID" sender:self];
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UIViewController *vcToPushTo = segue.destinationViewController;
vcToPushTo.propertyToSet = self.someProperty;
}

Segue using didSelectRowAtIndexPath

You need to declare selectedNote as optional like this:

  var selectedNote: Note?

And later check if value exist before using it.

  if let note = selectedNote {
// Set up the detail view controller to show.
let detailViewController = DetailViewController()
detailViewController.detailDescriptionLabel = note.valueForKey("noteBody") as! UILabel

// Note: Should not be necessary but current iOS 8.0 bug requires it.
tableView.deselectRowAtIndexPath(tableView.indexPathForSelectedRow()!, animated: false)
// original code
navigationController?.pushViewController(detailViewController, animated: true)
}

Update:

The problem is that you are trying to create DetailViewController

let detailViewController = DetailViewController()

But what you need instead is to have reference to the DetailViewController in order to pass information to it.

So you can create segue from Master to Detail controller in Interface builder. Then remove logic from didSelectRowAtIndexPath

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

// Note: Should not be necessary but current iOS 8.0 bug requires it.
tableView.deselectRowAtIndexPath(tableView.indexPathForSelectedRow()!, animated: false)
}

And implement it in prepareForSegue method:

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

if segue.identifier == "showDetail" {

if let cell = sender as? UITableViewCell {

let indexPath = tableView.indexPathForCell(cell)!

var selectedNote: Note?

if filteredObjects?.count > 0 {
selectedNote = filteredObjects![indexPath.row]
}else {
selectedNote = self.fetchedResultsController.objectAtIndexPath(indexPath) as? Note // <--this is "everything"
}

if let note = selectedNote {

let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
controller.detailItem = note
}
}
}
}

showDetail - segue identifier which you need to setup in IB.
var detailItem: AnyObject? - you need to declare it in DetailViewController.

in iOS app, why does prepareForSegue occur before didSelectRowAtIndexPath

Do you have your detail segue attached to the table view cell? Instead, try dragging it between the two view controllers (the one containing the table and the one where you want it to go).

Then perform it manually ([self performSegueWithIdentifier:@"MySegue"];) when tableView:accessoryButtonTappedForRowWithIndexPath:.

How to access segue in 'didSelectRowAtIndexPath'?

You should be using the didSelectRowAtIndexPath method to determine whether or not a cell was selected, and send the indexPath as the sender of the segue:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("showQuestionnaire", sender: indexPath);
}

Then in your prepareForSegue method, get the indexPath from the sender parameter and use that to pass the correct row/data:

override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "showQuestionnaire") {
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! QuestionnaireController
let row = (sender as! NSIndexPath).row; //we know that sender is an NSIndexPath here.
let patientQuestionnaire = patientQuestionnaires[row] as! PatientQuestionnaire
controller.selectedQuestionnaire = patientQuestionnaire
}
}

To explain...

  1. I used the index path as the sender so I can easily pass the index path. You could also check for the currently selected cell using other UITableView methods, but I've always done it this way with success
  2. You can't put performSegueWithIdentifier within the prepare for segue method, because performSegueWithIdentifier leads to prepareForSegue; You are just looping around and around with no aim. (When you want to perform a segue, prepareForSegue is always executed)
  3. prepareForSegue doesn't run by itself when a row is selected. This is where you need didSelectRowAtIndexPath. You need a performSegueWithIdentifier outside of the method as described previously, which should be in didSelectRowAtIndexPath

Sending indexPath.row from didselectRowAtIndexPath to prepareForSegue via sender

You should pass like this:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("notificationsToAnswers", sender: indexPath)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "notificationsToAnswers" {
//the below line is incorrect and should be something else
let selectedIndexPath = sender as! NSIndexPath
let index = selectedIndexPath.row
//pass data on using the index
}

}


Related Topics



Leave a reply



Submit