Уловки для улучшения прокрутки iPhone UITableView?

89

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

Я нашел эти советы в блоге FieryRobot:

гладкая прокрутка с uitableview

более гладкая прокрутка с возможностью просмотра

Есть ли у кого-нибудь советы по повышению производительности прокрутки uitableview?

Иона
источник
Если вам нужно кэшировать высоту ячеек (что может быть дорогостоящим для вычисления и также часто используется), я привел пример. Используйте его, только если он подходит для вашего приложения. stackoverflow.com/questions/1371223/…
Поль де Ланж

Ответы:

156
  1. Кэшировать высоту строк (представление таблицы может запрашивать это часто)
  2. Создайте кеш, который использовался не так давно, для изображений, используемых в таблице (и аннулируйте все неактивные записи, когда вы получите предупреждение о памяти)
  3. Нарисуйте все в UITableViewCellэлементах, drawRect:если возможно, избегайте подпредставлений любой ценой (или, если вам требуются стандартные функции специальных возможностей, представления содержимого drawRect:)
  4. Сделайте свой UITableViewCellслой непрозрачным (то же самое касается представления содержимого, если оно у вас есть)
  5. Используйте функциональность reusableCellIdentifier, как рекомендовано в UITableViewпримерах / документации.
  6. Избегайте градиенты / сложные графические эффекты, которые предварительно не запеченные в UIImageсек
rpetrich
источник
5
Кроме того, загруженные изображения должны быть уменьшены до размера imageView перед отображением в ячейке!
Золтан Маток
4
Я хотел бы добавить к этому ответу один из своих опытов за последние несколько лет - наличие прозрачных ячеек, вероятно, никогда не является причиной плохой прокрутки. У нас есть приложение с ОЧЕНЬ сложными ячейками (20+ подпредставлений), и все оно прозрачно для отображения фона. При правильной оптимизации прозрачность не имеет значения даже на 3GS. На самом деле, больше всего замедлялась загрузка пера до того, как было достаточно ячеек для удаления из табличного представления. Если вы используете подпредставления, просто убедитесь, что у вас эффективные иерархии, и вам не нужно использовать drawRect.
Accatyyc
@Accatyyc, похоже, у меня такая же проблема. Есть небольшая задержка, когда недостаточно ячеек для удаления, когда 3-4 ячейки удаляются, прокрутка плавная. Есть ли способ предварительно загрузить ячейки, чтобы оставались ячейки для удаления из очереди и не загружать файлы NIB при прокрутке?
Tiois
@Tiois Конечно, есть. Вам нужно использовать старый способ удаления ячеек из очереди (не регистрировать классы / перья, а создавать их, если dequeueCellWithIdentifier: возвращает nil). Таким образом, вы можете создать набор ячеек до того, как ваше табличное представление вообще появится, например, создав 20 из них раньше. Затем вместо создания новых в cellForRowAtIndexPath: вы сначала извлекаете их из собственного кеша, пока он не станет пустым.
Accatyyc
Я использую UICollectionView и сталкиваюсь с той же проблемой. В моем пользовательском файле пера ячейки. Я использую несколько подпредставлений, включая UIwebView и UIImageView внутри вертикального UIstackView. когда я прокручиваю список повторно используемых ячеек, требуется много времени, чтобы изменить их размер, и прокрутка выглядит очень прерывистой.
Мансуу .... 03
40
  1. Если вы создаете подклассы UITableViewCell, не используйте перо, вместо этого напишите его в коде. Это намного быстрее, чем загрузка файлов пера.
  2. Если вы используете изображения, убедитесь, что вы их кешируете, чтобы вам не приходилось загружать из файла более одного раза для каждого (если у вас есть память - вы удивитесь, сколько места занимают изображения).
  3. Сделайте как можно больше элементов непрозрачными. Точно так же старайтесь не использовать изображения с прозрачностью.
Лохматая лягушка
источник
3
не волнуйтесь ... это были тролли. отличный ответ!
Steav
79
Голосование против, вероятно, было вызвано тем, что «избегать перьев» - плохой совет для повышения производительности. Если вы повторно используете ячейки, они вообще не реконструируются из перьев при прокрутке.
Стивен Фишер,
6
По данным исследования «Какао с любовью», перья эквивалентны по скорости или немного быстрее. cocoawithlove.com/2010/03/…
MaxGabriel
@Steven Fisher, использующий Nib, может работать медленнее, когда таблица выделяет и освобождает ячейки, например - во время быстрой прокрутки.
Sound Blaster
3
Использование NIB может быть медленнее, когда ячейка строится . Если вы используете переработку ячеек, то ячеек выделено только для заполнения экрана; скажем, максимум 10. При прокрутке ячейки не создаются. Они просто повторно используются , а не освобождаются и не перераспределяются. И, конечно же, за освобождение не нужно платить. Так что нет, это неправильно.
Стивен Фишер
34

Разработчик Tweetie много писал об этом и имеет код, демонстрирующий, как это было сделано для этого приложения. По сути, он / она выступает за одно настраиваемое представление для каждой ячейки таблицы и отрисовывает его вручную (а не подпросмотр с помощью Interface Builder, среди других вариантов).

быстрая прокрутка в твити-с-uitableview

Кроме того, Apple обновила собственный пример кода для TableView в своих учебных пособиях TableViewSuite (может быть, в ответ на это?)

TableViewSuite

Бено
источник
1
Это отличное решение. Мне просто интересно, как мне добавить UIButton в cellView? Рисуется ли он в методе drawRect?
Sukitha Udugamasooriya 08
1
@beno, ваша ссылка кажется неработающей (первая), есть ли шанс заполучить оригинальную статью?
apouche
3
Исходную
добавлена ​​ссылка на веб-архив, так как оригинальной версии не существует
Ральф Уиллгосс
1

Убийца производительности №1 для прокрутки UITableView - это рисование тени на любом слое представления ячеек, поэтому, если производительность прокрутки имеет значение, не создавайте тени, если только это не замедляет ваш основной поток.

подумал, что это нужно сказать, поскольку ни в одном из принятых ответов не упоминались тени и слои. : +)

Джеки Джонсон
источник
6
если проблемы в тенях, добавьте эти две строки кода, и все работает отлично self.layer.shouldRasterize = YES; self.layer.rasterizationScale = UIScreen.mainScreen.scale;
Педро Ромао
0

Любую проблему с UITableViewпроизводительностью прокрутки можно решить с помощью методов, уже описанных в других ответах. Однако часто низкая производительность вызвана чем-то изначально ошибочным или повторяющимся.

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

  1. Загрузить данные в источник данных - из REST / базы данных. Этот шаг должен выполняться в фоновом режиме, в конечном итоге используя dispatch_async вместе с очередью GCD.
  2. Создавать и инициализировать соответствующие объекты модели данных и помещать их в массив
  3. [tableView reloaddata]
  4. Внутри cellForRowAtIndexPathвключите код, который установит данные (текст) из правильного объекта модели данных массива.
  5. Теперь изображения могут быть также в форме URL-адреса, поэтому этот шаг может быть немного необычным из-за повторного использования ячеек в табличном представлении. Суть заключается в том, чтобы снова загрузить изображение из кеша / URL-адреса устройства с помощью асинхронной очереди, а затем установить для него правильное значение cell.image (независимо от того, какое свойство изображения вашей ячейки).

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

Нирав Бхатт
источник