3
votes

It has been a while since I have done any iOS programming so please forgive me for the simple question. I have searched, and maybe I am just over thinking this.

I have a segue called ShowStreamDetails connecting dynamic prototype cells to a detail view that shows... details of the selected cell. Now I didn't know that the detail disclosure buttons was going to be troublesome. If I select the cell, it works correctly and passes objects to the detail view. If I press the detail disclosure indicator it goes to the detail view and that view then displays the first item on the list, instead of the actual item listed in the cell. So, here is what I have.

-(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:   
(NSIndexPath *)indexPath
{
  [self performSegueWithIdentifier:@"ShowStreamDetails" sender:[self.tableView cellForRowAtIndexPath:indexPath]];
}

and the prepare for segue:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{
    if ([[segue identifier] isEqualToString:@"ShowStreamDetails"]) 
    {
        StreamsDetailViewController *detailViewController = [segue destinationViewController];

        detailViewController.streams = [self.dataController objectInListAtIndex:[self.tableView indexPathForSelectedRow].row];
    }
}

How do I add this to the prepareForSegue: so that it passes the correct information?

3

3 Answers

1
votes

I just ran into this problem and managed to figure out that the sender parameter is the UITableView cell for the detail disclosure.

So just do something like this:

UITableViewCell* cell = (UITableViewCell*)sender;
IndexPath* iPath = [self.tableView indexPathForCell: cell];
1
votes

@voidref has the right idea.

The problem is that when the user taps the detail disclosure button, the cell doesn't get selected. So -indexPathForSelectedRow returns nil, which is treated as zero for purposes of the array index.

Instead you want to find the index path of the cell whose disclosure button triggered the segue. So your second block of code should look like:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{
    if ([[segue identifier] isEqualToString:@"ShowStreamDetails"]) 
    {
        StreamsDetailViewController *detailViewController = [segue destinationViewController];

        detailViewController.streams = [self.dataController objectInListAtIndex:[self.tableView indexPathForCell:sender].row];
    }
}

Also, not directly related to your original question, but you don't need to implement -tableView:accessoryButtonTappedForRowWithIndexPath:. Instead, just set your prototype cell's accessory type to Detail Disclosure in the storyboard, and control/two-finger/right-drag from the accessory button in your prototype cell to your detail view controller, and then name the resulting segue "ShowStreamDetails".

Even though the accessory button is arguably the "sender", the sender parameter will be set to the table view cell automatically.

0
votes

Version in Swift:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let shooterController = segue.destination as? UIShooterViewController {
        if let cell = sender as? UITableViewCell, let indexPath = tableView.indexPath(for: cell) {
            let matchShooter = fetchedResultsController.object(at: indexPath)
            shooterController.setEntity(matchShooter.shooter, new: false)
        }
    }
}

Sender contains Cell in which disclosure indicator was tapped.