Лучшие практики для рисования динамической высоты строки UITableView - PullRequest
10 голосов
/ 28 сентября 2011

Возможно, дубликат, но я не смог найти конкретный вопрос по SO, поэтому вот он.

Мне интересно узнать о динамическом изменении высоты для всех строк, как правило, потому что вы не знаете длину строки NSString, используемой для метки.

Я знаю, что вы должны использовать этот метод делегата для изменения высоты строк:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

Проблема в том, что этот метод-делегат называется ДО создания ячейки (т.е. вызывается до cellForRowAtIndexPath).

Итак, я подумал о том, чтобы создать фиктивную ячейку в viewWillAppear и метод, который добавляет высоту ячейки к массиву, который сопоставляется с источником данных табличного представления (который в моем случае также является массивом).

viewWillAppear реализует этот важный метод для получения высоты:

[NSString sizeWithFont: constrainedToSize: lineBreakMode:]

Тогда в heightForRowAtIndexPath я могу вернуть высоту ячейки так:

//cellHeights is an ivar populated in viewWillAppear
return [[cellHeights objectAtIndex:indexPath.row] floatValue];

Мне было интересно, есть ли лучший способ динамического изменения высоты строки?

Я понимаю, что это приведет к снижению производительности для большого количества строк (я думаю, больше 1000). Но в моем случае мои строки никогда не приблизятся к этому числу. Таким образом, снижение производительности незначительно.

Заранее спасибо!

Ответы [ 3 ]

8 голосов
/ 28 сентября 2011

Отличный вопрос! На самом деле я делал нечто подобное в некоторых своих приложениях.

Я могу придумать пару альтернатив, но все они связаны с одной и той же темой. Вы также можете просто использовать 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, я полагаю, что вы в конечном итоге делаете это для каждой ячейки, независимо от того, отображается ли она?

Наконец, вы можете указать размер самой модели данных. Если это, например, массив строк, вы можете создать класс с двумя свойствами: строкой и свойством "presentationSize". Затем вы можете пересчитывать размер строки каждый раз, когда значение строки изменяется. Тогда будет только один массив, а не два, который будет отображаться в вашем источнике данных, заполненный классом данных, содержащим как строку, так и размер отображения строки, и значение будет вычислено при изменении строки, а не за один раз. когда появится вид.

В любом случае, я хотел бы услышать некоторые комментарии об этих различных подходах.

1 голос
/ 06 ноября 2013

У меня тоже проблема с UITableView при прокрутке таблицы (на iPhone 3gs).Я видел много лагов.Поэтому я открываю профилировщик времени (очень хороший инструмент для оптимизации), и проблема была, когда я вызываю функцию sizeWithFont.Лучшим решением для решения этой проблемы является вызов sizeWithFont в конструкторе.

1 голос
/ 07 октября 2011

Идея Мэтью поместить высоту в модель данных звучит интересно.Вот еще один ответ, который предлагает очень похожее решение: Как правильно сделать ячейки таблицы переменной высоты на iPhone?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...