Рекомендации по рисованию динамической высоты строки UITableView
Возможно, дубликат, но я не мог найти конкретный вопрос о SO, так что вот оно.
Мне интересно узнать динамически изменяющиеся высоты для всех строк, как правило, потому что вы не знаете длину NSString, которая использовалась для метки.
Я знаю, что вы должны использовать этот метод делегата для изменения высоты строки:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
Проблема заключается в том, что этот метод делегата называется ПЕРЕД тем, как создается ячейка (т.е. вызывается до cellForRowAtIndexPath
).
Итак, я думал о создании mock-ячейки в viewWillAppear
и методе, который добавляет высоты ячеек в массив, который сопоставляется с источником данных таблицы (который в моем случае также является массивом).
viewWillAppear
реализует этот важный метод для получения высоты:
[NSString sizeWithFont: constrainedToSize: lineBreakMode:]
Затем в heightForRowAtIndexPath
я могу вернуть высоту ячейки так:
//cellHeights is an ivar populated in viewWillAppear
return [[cellHeights objectAtIndex:indexPath.row] floatValue];
Мне было интересно, есть ли лучший способ динамически изменять высоту строки?
Я понимаю, что это ухудшит производительность для большого количества строк (я полагаю, более 1000). Но в моем случае мои ряды никогда не приблизится к этому числу. Таким образом, удар производительности ничтожно мал.
Спасибо заранее!
Ответы
Ответ 1
Отличный вопрос! Фактически, я сделал что-то подобное в некоторых моих приложениях.
Я могу вспомнить пару альтернатив, но все они по одной теме. Вы также можете просто использовать sizeWithFont:
внутри heightForRowAtIndexPath:
и покончить с массивом. В этом случае вы можете получить удар производительности для пересчета размера каждый раз, если эта операция стоит дорого.
Вы можете сделать "ленивую загрузку" массива cellHeights внутри heightForRowAtIndexPath:
, чтобы он выглядел примерно так:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([cellHeights objectAtIndex:indexPath.row] == nil) {
... calculate height and store it in the array at the correct index...
}
return [[cellHeights objectAtIndex:indexPath.row] floatValue];
}
Преимущество, о котором я сейчас думаю, заключается в том, что вы только вычислите высоты для ячеек, которые определенно будут загружены. Если вы выполните расчет в viewWillAppear
, я думаю, вы в конечном итоге делаете это для каждой ячейки, независимо от того, отображается ли она?
Наконец, вы можете поместить размер в свою модель данных. Если это, например, массив строк, вы можете создать класс, который имеет два свойства: строку и свойство "представление". Затем вы можете пересчитать размер строки каждый раз при изменении значения строки. Тогда будет только один массив, а не два, который будет отображаться на ваш источник данных, заполненный классом данных, содержащим как строку, так и размер отображения строки, и значение будет вычисляться, когда строка изменяется, а вовсе не раз когда появится представление.
В любом случае, я хотел бы услышать некоторые комментарии по этим различным подходам.
Ответ 2
Идея Мэтью поместить высоту в модель данных звучит интересно. Вот еще один ответ, который предлагает очень похожее решение: Как я могу сделать таблицы таблицы высот таблицы на iPhone правильно?
Ответ 3
У меня тоже проблема в UITableView, когда я прокручиваю табличное представление (на iPhone 3gs). Я видел много лагов. Поэтому я открываю время профилировщик (очень хороший инструмент для оптимизации), и проблема заключалась в том, что я вызываю функцию sizeWithFont. Лучшим решением для решения этой проблемы является call sizeWithFont в конструкторе.