Использовать метод didSelectRowAtIndexPath или prepareForSegue для UITableView?


101

Я использую раскадровки, и у меня есть UITableView. У меня есть настройка перехода, которая перемещается из моей таблицы в подробный VC. Но какой метод я должен использовать, чтобы справиться с этим? Мне нужно передать пару объектов в подробное представление. Но я использую didSelectRowAtIndexили-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender ?

Ответы:


199

Если вы используете, prepareForSegue:sender:то вам не нужно будет так много менять, если вы позже решите запустить переход из какого-либо элемента управления за пределами табличного представления.

prepareForSegue:sender:Сообщение отправляется на текущий контроллер представления, так что я хотел бы предложить что - то вроде этого:

- (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];
}

В Swift:

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

1
Хорошо, вы можете привести пример того, как это реализовать с передачей объекта на основе indexPath.
Джон

4
не должно self.viewбыть просто senderздесь? Я даже не мог приступить [self.view indexPathForSelectedRow]к работе, мне нужно было это сделать[sender indexPathForSelectedRow];
Ladookie

Как бы вы сделали это в Swift?
User

@robmayoff Спасибо, что обновили это для Swift. Я внес небольшие правки, чтобы отразить недавние языковые изменения. Надеюсь, это поможет некоторым другим
Зак Шапиро

Странно, что tableView.indexPathForSelectedRow()при prepareFroSegue...вызове содержится правильное значение : tableView(_:didSelectrowAtIndexPath:)вызывается позже.
Николас Миари 07

5

Я сделал это, и это сработало

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

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

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

11
В этом нет смысла. Вы должны использовать либо переход, либо делегат табличного представления. Просто создайте переход из ячейки, и он автоматически выполнит то же самое, что и вы, без написания кода.
Yariv Nissim

3
как назначить переход ячейке без didSelectRow?
Morkrom

3

Если отправителем является UITableViewCell, вы можете попросить UITableView запросить indexPath ячейки.

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

1

если ваше свойство tableView находится в другом классе и у вас есть только один раздел , вы можете использовать tagсвойство для хранения строки ячейки, например:

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

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

     cell.tag = indexPath.row;

     return cell;
}

И тогда вы можете получить к нему доступ, поскольку senderэто та же ячейка со значением строки в ее теге:

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

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

1

self.tableView.indexPathForSelectedRowвозвращает выбранную ячейку, но не сохраняет ячейку отправителя, например, ячейка отправителя не выбрана (дополнительное действие) или в случае множественного выбора. Лучший способ - получить indexPath для отправителя segue:

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

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

0

Если вы используете, prepareForSegue:вы можете проверить, кто является отправителем, и выполнить другой код

Например в быстром

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

   if senderIsTableviewCell
   {
       //do something
   }
}

2
Просто сделайте: if let tableViewCell = sender as? UITableViewCell {// что-то делать} . Если отправитель не может быть приведен к UITableViewCell, «сделать что-нибудь» не будет выполнено.
mbeaty 04
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.