对 UITableView 使用 did SelectRowAtIndexPath 方法或 prepareForSegue 方法?

我使用故事板,我有一个 UITableView。我有一个接续设置,从我的表推到详细风险投资。但是我应该使用哪种方法来处理这个问题呢?我必须向细节视图传递几个对象。但是我应该使用 didSelectRowAtIndex还是 -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender呢?

73069 次浏览

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)
}

I did this and it worked

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{


NSLog(@"Row Selected = %i",indexPath.row);


[self performSegueWithIdentifier:@"testID" sender:self.view];
}

If you use prepareForSegue: you can check who is the sender and execute different code

For example in swift

override func prepareForSegue(segue: UiStoryboardSegue, sender: AnyObject?)
{
var senderIsTableviewCell:Bool! = sender?.isKindOfClass(UITableViewCell)


if senderIsTableviewCell
{
//do something
}
}

if your tableView property is in another class and you only have one section, then you could use the tag property to store the cell's row like:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {


UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];


cell.tag = indexPath.row;


return cell;
}

And then you can access it as the sender is the same cell with the row value in its tag:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {


MyDestinationViewController *destinationViewController = segue.destinationViewController;
destinationViewController.myProperty = [tableViewElementsArray objectAtIndex:[sender tag]]; // sender will be your cell
}

When sender is UITableViewCell, you may ask UITableView to query indexPath of the cell.

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let cell = sender as? UITableViewCell {
let indexPath = self.tableView.indexPathForCell(cell)!
assert(segue.destinationViewController.isKindOfClass(DetailViewController))
let detailViewController = segue.destinationViewController as! DetailViewController
detailViewController.item = self.items[indexPath.row] // like this
}
}

self.tableView.indexPathForSelectedRow returns selected cell, but not segue sender cell, e.g. sender cell is not selected (accessory action), or in multiple selection case. The best way is getting indexPath for segue sender:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
__auto_type itemViewController = (id<ItemViewController>)segue.destinationViewController;
itemViewController.senderIndexPath = [self.tableView indexPathForCell:sender];
}

In Swift:

protocol ItemViewController {
var senderIndexPath : IndexPath? { get set }
var selectedIndexPaths : [IndexPath]? { get set }
}


override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if  let cell = sender as? UITableViewCell,
var itemViewController = segue.destination as? ItemViewController {
itemViewController.senderIndexPath = tableView.indexPath(for: cell)
itemViewController.selectedIndexPaths = tableView.indexPathsForSelectedRows
}
}