Вызов 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 13

1 ответ:

Проблема в том, что UITableView запрашивает у вашего источника данных данные, и вы говорите ему, что ответ зависит от данных, которые он может или не может кэшировать.

Вы неправильно поняли схему M-V-C, на которой Apple основывает свои элементы управления. Ответ на вопрос о высоте строки должен исходить от модели, а не от обратного вызова класса view. Это приводит к тому, что класс view запрашивает дополнительную информацию (для построения своего внутреннего кэша), который запускает набор рекурсивных звонки.

Убедитесь, что все методы делегирования источника данных возвращают данные из вашей модели и не полагаются на кэширование представления. Если вы отладите любое представление на основе источника данных, вы будете удивлены, сколько раз UITableView запрашивает данные. Но именно так Apple его и закодировала.