Сбой IndexPathForCell и IndexPathForRowAtPoint

У меня есть UITableViewController со статическими сгруппированными ячейками. В конкретном представлении я хочу удалить некоторые ячейки. Если я просто скрою их, останется пустое место, поэтому вместо этого я хочу установить для ячейки rowHeight значение 0. У меня возникли проблемы с этим, потому что я не могу получить indexPath ячейки, которую хочу скрыть. У меня есть ссылка на него через IB соединение. После прочтения кажется, что лучший способ сделать это — использовать метод heightForRowAtIndexPath. Вот мой код:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSIndexPath *myIndexPath = [self.tableView indexPathForRowAtPoint:self.billToPostalCell.center]; 
    //crashes here

    if ([indexPath isEqual:myIndexPath]) {
        return 0; 
    }
    return 44;
}

До этого пробовал IndexPathForCell, но тоже вылетало. Из того, что я прочитал, heightForRowAtIndexPath должно работать, даже когда ячейки не видны. При сбое в отладчике тоже ничего не появляется.


person abc123    schedule 22.04.2013    source источник
comment
Вы пытались выйти из строки, возвращенной myIndexPath?   -  person The Kraken    schedule 23.04.2013


Ответы (3)


То, что вы делаете, вызывает бесконечную рекурсию, ведущую к... подождите... переполнение стека!

Внутри метода heightForRowAtIndexPath: вы не можете запросить таблицу для ячейки или indexPath для строки, потому что эти методы должны знать высоту ячейки. Таким образом, эти вызовы приводят к вызову heightForRowAtIndexPath:. И поскольку вы затем снова вызываете те же оскорбительные методы, это продолжается до тех пор, пока все не пойдет в гору.

Поскольку ваша цель — скрыть ячейки, вы должны удалить ячейки из таблицы, используя правильный метод UITableView (deleteRowsAtIndexPaths:withRowAnimation:). Конечно, вам нужно сначала обновить модель данных (чтобы удалить строки).

person rmaddy    schedule 22.04.2013
comment
Спасибо, а как именно сначала обновить модель данных? Это статические ячейки с подключенными к IB UITextFields и UILabels в них, которые заполняются индивидуально в методе viewWillAppear. Простой вызов метода deleteRowsAtIndexPaths:withRowAnimation вызывает эту ошибку: 'NSInternalInconsistencyException', причина: 'Недопустимое обновление: недопустимое количество строк в разделе 4. Из Google я знаю, что мне нужно обновить модель источника данных, как вы сказали. - person abc123; 23.04.2013
comment
Ваш метод 'numberOfRowsForSection` должен возвращать число, основанное на некоторой модели данных, которая у вас есть (не жестко запрограммировано на какое-то конкретное значение). Это та модель данных, которую вам нужно обновить. Обычно это какой-то массив. Сначала удалите объект из массива, а затем скажите таблице удалить строку. - person rmaddy; 23.04.2013
comment
Вот в чем дело. В данном случае массива нет. Делегат dataSource tableView не подключен к контроллеру представления. И я не реализую ни один из методов делегата dataSource. Каждая ячейка, нарисованная в IB, имеет текстовое поле, связанное с кодом через выход IB. Затем в коде я заполняю текстовые поля следующим образом: self.myTextField.text = self.customer.someString. Я попытался установить ячейку на ноль, прежде чем удалить строку, но без кубиков. - person abc123; 23.04.2013
comment
Я нашел этот ответ, который помог мне в моих последующих вопросах. stackoverflow.com/a/9434849/1672161 Спасибо за ответ на мой первоначальный вопрос. - person abc123; 23.04.2013

Вы не должны изменять видимость и высоту ячеек. Если вы хотите удалить ячейки и добавить их обратно позже или никогда не добавлять их обратно, вы должны использовать методы вставки и удаления в UITableView. Вот хорошая отправная точка документация.

Кроме того, вы не должны использовать методы для tableView изнутри tableView:heightForRowAtIndexPath:, например indexPathForRowAtPoint:, поскольку tableView должен определить свою собственную высоту, прежде чем он сможет вычислять такие вещи. Вы, вероятно, получаете сообщение об ошибке, потому что находитесь в бесконечном цикле.

person Michael Reneer    schedule 22.04.2013

Используйте -deleteRowsAtIndexPaths:withRowAnimation для удаления строк. Никогда не манипулируйте видимостью ячейки вместо ее удаления; это может привести к серьезным проблемам с памятью и является просто плохой практикой. Просто введите NSArray, заполненный NSIndexPath строкой, которую вы хотите удалить.

Вы упомянули, что метод indexPathForRowAtPoint: не работает. Это почти наверняка проблема с точкой, которую вы передаете ей. Обязательно отключите значение billToPostalCell.center, чтобы убедиться, что вы передаете допустимое значение. Однако на самом деле нет необходимости делать это, если вы имеете дело со статическими ячейками, поскольку вы уже должны знать путь к индексу (по крайней мере, для первоначального удаления ячейки).

Как уже упоминалось, документация по удалению ячеек содержит всю необходимую дополнительную информацию.

person The Kraken    schedule 22.04.2013
comment
Это хороший момент, о котором я забыл упомянуть, поскольку вы используете статические ячейки, просто сравните их со статическим indexPath.row. - person Michael Reneer; 23.04.2013