IndexPathForSelectedRow возвращает ноль

У меня есть UITableViewController с segue, где я пытаюсь получить текущую выбранную строку:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if([[segue identifier] isEqualToString:@"EditFilterElementSegue"]){
        // Get the element that was clicked and pass it to the view controller for display
        NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
        Element *element = [fetchedResultsController objectAtIndexPath:selectedIndexPath];
        FilterElementTableViewController *vc = segue.destinationViewController;
        vc.filter = filter;
        vc.element = element;
    }
}

Проблема заключается в том, что indexPathForSelectedRow возвращает nil. Документы говорят, что nil возвращается "если указательный путь недействителен". Если я добавлю:

        [self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:YES scrollPosition:0];
        selectedIndexPath = [self.tableView indexPathForSelectedRow];

selectedIndexPath действителен. Итак, я в настоящее время предполагаю, что строка как-то становится невыбранной. Может ли кто-нибудь сказать мне, как выяснить, если это так и что может быть причиной?

Этот код работал нормально, пока я не переработал NSFetchedResultsController (который в противном случае работает). Я также использую indexPathForSelectedRow в нескольких других контроллерах табличных представлений, где он отлично работает (один из которых также использует NSFetchedResultsController).

Я также пытался взломать didSelectRowAtIndexPath, но то же самое происходит там. (ожидается, поскольку он вызвал после prepareForSegue.)

Ответы

Ответ 1

Хорошо, нижняя строка сцены в раскадровке была испорчена.

Чтобы понять это, я удалил segue и создал совершенно новый пустой класс UITableViewController и добавил только достаточно кода, чтобы я мог щелкнуть по строке и посмотреть на indexPathForSelectedRow. Это было еще ноль.

Затем я создал новый UITableViewController в раскадровке и заменил существующий. Теперь работал indexPathForSelectedRow.

Я скопировал весь код класса и прототипы ячеек, и он все еще работает!

Из любопытства я посмотрел источник раскадровки на две сцены и заметил, что сцена, которая не работала, была намного длиннее новой. Глядя на схему раскадровки, было очевидно, почему, и удивительно, что это сработало. И теперь я помню, что у меня были проблемы с резанием и вклеиванием прототипа. Думаю, я должен чаще смотреть на схему. См. Снимок экрана ниже (визуальные сцены выглядят одинаково):

Storyboard screen shot

Ответ 2

Возможная причина в том, что вы написали что-то в одном из методов UITableViewDelegate -

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

Это обычная практика только для deselect the row.

Ответ 3

Что-то, что может помочь другим пользователям - если вы вызываете reloadData() в своем представлении таблицы, это означает indexPathForSelectedRow.

Ответ 4

Убедитесь, что вы не вызываете метод deselectRowAtIndexPath, прежде чем получить путь указателя к выбранному столбцу.

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES]; //add this line after setting indexPath
}

Ответ 5

Хорошо. В моем случае я звонил из UIButton в раскадровке с помощью show segue.

И удаление следующей строки:

NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];

с ниже 2 строк работал у меня:

CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView]; NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];

надеюсь, что мой случай "вызов segue из UIButton on CELL" также работает и для других.

Ответ 6

У меня также была эта проблема, когда я заменил класс UITableViewController классом UIViewController в коде и не обновлял раскадровку, то есть я не заменил заполнитель UITableViewController в раскадровке с раскадрой UIViewController.