Вызов numberOfRowsInSection: from 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:, он вызывает мой метод datasource tableView: numberOfRowsInSection:. Это имеет смысл, поскольку метод tableView возвращает кешированную версию значения источника данных, поэтому ему необходимо сначала получить значение из источника данных. Но тогда он вызывает heightForRowAtIndexPath, передавая ему indexPath [0, 0] снова! И он делает это без остановок.

Мне удалось обойти это, используя

[self tableView:tableView numberOfRowsInSection:indexPath.section]

вместо этого (вызов метода datasource вместо метода tableView). У кого-нибудь есть идея, почему он это делает? Это определенное поведение? Или ошибка в структуре Apple TableView?

Ответы

Ответ 1

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

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

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