heightForRowAtIndexPath вызывается для всех строк и сколько строк в UITableView до проблем с производительностью?

Я думал, что читал, что для UITableView heightForRowAtIndexPath вызывается не для всех строк, а только для тех, которые будут видны. Однако это не то, что я вижу. Я вижу сотни вызовов heightForRowAtIndexPath, например, для простой ситуации изменения ориентации iPhone.

Поэтому я предполагаю, что для UITableView с реализованным heightForRowAtIndexPath он (т.е. heightForRowAtIndexPath) вызывается для всех строк (а не только для видимых)... дайте мне знать, если это не совсем правильно.

ВОПРОС. Учитывая вышеизложенное, сколько строк в UITableView (где реализован heightForRowAtIndexPath) можно иметь до того, как обычно возникнут проблемы с производительностью?

Есть ли способ обойти проблемы с производительностью? то есть установить номинальную/стандартную высоту для каждой строки и не реализовывать heightForRowAtIndexPath, но затем правильно установить высоту каждой строки только тогда, когда она отображается, и правильно установить ее здесь ... но каким методом это можно сделать?


person Greg    schedule 16.03.2011    source источник


Ответы (4)


Просмотрите раздел обсуждения в tableView:heightForRowAtIndexPath: документация

Метод позволяет делегату указывать строки с разной высотой. Если этот метод реализован, возвращаемое им значение переопределяет значение, указанное для свойства rowHeight UITableView для данной строки.

Использование tableView:heightForRowAtIndexPath: вместо свойства rowHeight влияет на производительность. Каждый раз, когда отображается табличное представление, оно вызывает tableView:heightForRowAtIndexPath: для делегата для каждой из его строк, что может привести к серьезной проблеме производительности с табличными представлениями, имеющими большое количество строк (приблизительно 1000 или более).

Поэтому вы должны использовать свойство rowHeight UITableView. Если вам нужны разные высоты, вам не повезло, потому что вы должны использовать tableView:heightForRowAtIndexPath:.

Насколько я знаю, нет способа изменить высоту строки при отображении.
Табличное представление должно знать правильный размер раньше, иначе все время будут уродливые сдвиги позиции.

person Matthias Bauch    schedule 16.03.2011
comment
о, но опять же, у меня здесь табличное представление с примерно 500 элементами, и производительность кажется плохой - так что это может означать, что вы действительно не можете иметь tableView с таким количеством строк в нем, нет? - person Greg; 16.03.2011
comment
это означает, что у вас не может быть 500 строк с разной высотой. Если все строки имеют одинаковую высоту (заданную в свойстве rowHeight), это не должно сильно влиять на производительность. - person Matthias Bauch; 16.03.2011
comment
Я действительно хочу, чтобы Apple исправила этот дефект, связанный с невозможностью динамической высоты строк с большим количеством строк. Мне было бы интересно узнать, есть ли какой-либо другой способ динамического управления количеством строк в UITableView, чтобы сохранить минимальные числа. - person geekinit; 23.12.2011
comment
На самом деле я не совсем уверен, что они смогут это исправить. По совершенно другой причине я начал разрабатывать свой собственный tableView с намерением воссоздать функциональность Apple и добавить свои собственные. Я быстро понял, что мне нужно знать высоты всех ячеек, чтобы заставить его работать. Поскольку вы не можете предсказать, где будет находиться таблица (она может программно прыгать), вы должны быть готовы к размещению представлений в любом месте, что означает, что вы должны знать все высоты. Единственной альтернативой является вычисление всех предыдущих высот для каждого макета, что было бы чрезмерно дорого. - person Aaron Hayman; 17.04.2012
comment
это убивает меня, но, по крайней мере, у меня есть ответ. Вы думаете, что они могли бы, по крайней мере, сделать так, чтобы они вычисляли, скажем, первые 50 строк, а затем вычисляли остальные в пакетах на лету, когда пользователь прокручивает, как они делают с fethBatchSize в CoreData. Мое приложение иногда будет иметь более 1000 строк, а некоторые из них МОГУТ иметь другой размер строки - загружаются сокрушительно медленно - person Slee; 07.12.2012
comment
Просто OMG, только что столкнулся с этим. Просто OMG на этом дизайне. - person ort11; 27.02.2015

Думаю, я нашел решение.

В iOS 7 Apple представила несколько новых свойств tableview. Одним из них является:

tableView:estimatedHeightForRowAtIndexPath:

Таким образом, если вы указываете предполагаемую высоту строки, например, когда tableView:heightForRowAtIndexPath: вызывается повторно перед отображением таблицы, она вызывается только для видимых ячеек таблицы; для остальных ячеек используется расчетная высота.

Вот источник этой информации: https://books.google.gr/books?id=wLaVBQAAQBAJ&pg=PT521&lpg=PT521&dq=heightforrowatindexpath+only+for+the+visible+cells&source=bl&ots=7tuwaMT5zV&sig=h3q8AaFvoCgcrPu2fQchVkIEjwg&hl=en&sa=X&ved=0CEMQ6AEwBWoVChMInLK0xbPuxwIVCbUaCh3_nQWG#v=onepage&q=heightforrowatindexpath%20only%20for%20the%20visible%20cells&f=false

person arniotaki    schedule 11.09.2015

Боже мой, я потратил больше часа, пытаясь найти источник моей проблемы с производительностью!

Наконец, я также нашел сотни вызовов heightForRowAtIndexPath, и поиск дал мне эту тему. ЭТО действительно раздражает. Производительность снижается уже при отображении 250 элементов. К счастью, все ячейки, которые я хочу отобразить, имеют одинаковый размер. Но я могу представить, что кто-то захочет отобразить несколько разных ячеек для tableView с > 200 элементами!

ИСПРАВЬТЕ ЭТО ЯБЛОКО!

Ваше здоровье

person Mario    schedule 16.04.2012

Способ повысить производительность в tableViews с большим количеством строк и динамической высотой ячеек — кэшировать высоту ячеек после их первого вычисления.

Упрощенный подход для достижения этого состоит в том, чтобы сохранить NSMutableDictionary, в котором ключом является идентификатор записи в ячейке (или любой другой идентификатор, который у вас может быть), а значением является NSNumber с высотой строки. После первого расчета высоты сохраните ее NSMutableDictionary по идентификатору записи. В tableView:heightForRowAtIndexPath и tableView:estimatedHeightForRowAtIndexPath: вы проверяете кешированную высоту в словаре и возвращаете ее, если она найдена. Если не найдено, вычислите высоту и сохраните в кеше перед возвратом высоты.

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

У вас все еще может быть удар по производительности, если вы попытаетесь отобразить 1000 ячеек одновременно, когда отображается таблица, поскольку он, вероятно, вызовет метод высоты для каждой строки. Обходной путь для этого заключается в том, чтобы сначала разогреть кеш, если это возможно в фоновой задаче, перед первым отображением ячеек.

person rantunes    schedule 09.02.2016