Вызов numberOfRowsInSection: из heightForRowAtIndexPath
Только что обнаружил очень странное и неожиданное поведение в классе UITableView. Мне нужно, чтобы последняя ячейка таблицы в моем разделе была разной высоты от других ячеек, поэтому я делаю в основном следующее:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == [tableView numberOfRowsInSection:indexPath.section] - 1)
return 44;
else
return 88; //double size for all but the last row
}
Кажется довольно прямолинейным, но когда я запускаю его, я получаю бесконечный цикл, и он падает. Я определил, что когда я вызываю numberOfRowsInSection:
, он вызывает метод tableView: numberOfRowsInSection:
моего источника данных. Это имеет смысл, поскольку метод tableView возвращает кэшированную версию значения источника данных, поэтому он должен получить значение из источника данных в первый раз. Но затем он вызывает heightForRowAtIndexPath, передавая его indexPath [0, 0] снова! И делает это безостановочно.
Я смог обойти его с помощью
[self tableView:tableView numberOfRowsInSection:indexPath.section]
Вместо этого (вызов метода источника данных вместо метода tableView). У кого-нибудь есть идеи, почему он это делает? Является ли это определенным поведением? Или ошибка в фреймворке Apple TableView?
1 ответ:
Проблема в том, что UITableView запрашивает у вашего источника данных данные, и вы говорите ему, что ответ зависит от данных, которые он может или не может кэшировать.
Вы неправильно поняли схему M-V-C, на которой Apple основывает свои элементы управления. Ответ на вопрос о высоте строки должен исходить от модели, а не от обратного вызова класса view. Это приводит к тому, что класс view запрашивает дополнительную информацию (для построения своего внутреннего кэша), который запускает набор рекурсивных звонки.
Убедитесь, что все методы делегирования источника данных возвращают данные из вашей модели и не полагаются на кэширование представления. Если вы отладите любое представление на основе источника данных, вы будете удивлены, сколько раз UITableView запрашивает данные. Но именно так Apple его и закодировала.