Подтвердить что ты не робот

Что такое приемлемый FPS для прокрутки и какие советы для повышения производительности?

Я вижу во многих видеороликах WWDC, которые говорят, что вы хотите достичь 60.0 FPS как можно ближе, чтобы получить более плавный прокрутка. У меня есть UIScrolLView, который одновременно загружает изображение и пару табличных представлений. В настоящее время я получаю 30 FPS. Это половина того, что рекомендуется FPS. Просто интересно, что FPS вы, ребята, обычно получаете за представление таблицы/прокрутки, которое загружает изображения и другие тяжелые вещи/материалы рендеринга.

Любые другие советы по оптимизации FPS? Я потратил на прошлой неделе до сих пор стрельбу по инструментам, используя инструмент профилирования времени, распределения и основной анимации для оптимизации, насколько я могу.

Просто чтобы немного уточнить, что у меня есть. У меня есть макет/водопад/pinterest стиль макет на IPad. Таким образом, это не просто обычный UITableView. Это UIScrollView, который заполняет весь экран и заполняется несколькими UIView. Каждое из этих представлений имеет 150x150 UIImageView и UITableView, а также имеет некоторую атрибутивную метку, нарисованную с использованием Core Text. Итак, на первый взгляд, когда вы видите экран, вы можете увидеть 5-8 табличное представление на одном снимке, каждая ячейка снова имеет UIImageView, а затем каждая ячейка отображает атрибутную метку, нарисованную с использованием основного текста.

Итак, вы можете просто представить, насколько это глубокое и сложное. Это не просто обычный табличный вид с UIImageView. Я знаю, как получить 60 FPS только с одним UITableView в iPhone с UIImage. Концепция заключается в том, чтобы загружать изображения асинхронно и не блокировать основной поток как можно больше.

EDIT:

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

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

4b9b3361

Ответ 1

Многие факторы влияют на производительность рендеринга, вот некоторые пункты, которые вы можете проверить:

  • Профиль - Вы сказали, что уже сделали это, так здорово! К сожалению, профилирование часто игнорируется, хотя оно может выявить неожиданные проблемы. В одном приложении я работал над календарем с разными ячейками, представляющими даты. Сначала прокрутка между ячейками медленная, что было неожиданным. Я подумал, что, может быть, это было слишком много клеток. После профилирования я обнаружил, что [NSCalender currentCalender] использовал 85% моего процессорного времени! После исправления, что все прокручивается отлично!

  • Изображения. Большие изображения загружают большую нагрузку в CoreGraphics. Для прокрутки особенно требуется много операций рисования, чтобы перемещать их. Одним из советов является масштабирование изображений на устройстве настолько, насколько это возможно, что делает работу CoreGraphics намного проще. Если изображение в два раза больше изображения, отображаемого на нем, измените размер UIImage перед его отображением в представлении. Устройства iOS лучше всего обрабатывают PNG. Они сжимаются инструментом (pngcrush) во время компиляции, и у iOS есть специальное оборудование для их рендеринга.

  • Пользовательский чертеж. Если возможно, сократите количество пользовательских рисунков CGContext, которые вы делаете. Множество пользовательских чертежей негативно сказывается на скорости анимации. Я бы подумал об использовании изображения над сложным пользовательским рисунком, если это возможно.

  • Cull - Делайте только то, что вам нужно. UITableView автоматически выгружает и загружает ячейки по мере их появления, поэтому это делается для вас, но любой пользовательский рисунок CGContext должен выполняться только тогда, когда эта часть видна. Кроме того, автоматические тени могут быть очень медленными в моем опыте.

  • Повторное использование. Используйте идентификатор повторного использования на UITableView, это позволит UITableView повторно использовать объекты ячеек, а не перераспределять их по мере прокрутки - посмотрите на ответ question. Также повторно используйте UIImages вместо выделения нескольких для одного и того же файла. imageNamed автоматически кэширует изображения, но imageFromContents файла не работает.

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

  • Последнее средство - уменьшает размер нарушающего представления (улучшает фильтрацию), разбивает содержимое на несколько страниц, уменьшает размер изображений, вырезает старые устройства, которые также не работают. Я бы согласился на 30 FPS, прежде чем жертвовать большей частью этого материала. Устройства будут продолжать работать быстрее, старые устройства будут устранены, и ваше приложение будет постепенно ускоряться.

Ответ 2

Я приближаюсь к 60 fps с моим UITableViewController, где таблица содержит около 2000 ячеек, и каждая ячейка извлекает изображение из Интернета. Трюк заключается в ленивой загрузке изображений по мере необходимости. Этот образец кода от Apple довольно полезен.

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

Ответ 3

Я бы сделал что-то, называемое Lazy Loading, которое не загружает изображения, пока они не будут видны.

Вот отличный пример того, как это сделать: http://www.cocoacontrols.com/platforms/ios/controls/mhlazytableimages

Удачи!

Ответ 4

Что я сделал, это использовать NSCache. Я создал небольшой класс со свойствами, которые соответствуют протоколу данных NSCache (его очень легко сделать). Таким образом, я создаю отношения между каждой ячейкой в ​​главной таблице и различными целями, которые стоит кэшировать: строками NSAttributed, изображениями и т.д. - действительно все, что требует работы для создания. Я не загружаю его, но вы можете.

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

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

Еще одна вещь, которую нужно помнить - убедитесь, что когда-либо просмотр, который может быть установлен в opaque, имеет свойство "YES". Это, безусловно, помогает системе визуализировать ячейку (в том числе представление backgound, если вы используете его.)

EDIT:

Итак, вы предоставили информацию, которая включала UITableViews, может быть проблемой root. Итак, два предложения:

1) Можете ли вы отступить и выяснить, как сделать scrollView одним UITableView? С верхними колонтитулами и нижними колонтитулами разделов и верхними колонтитулами разделов и даже возможностью по существу сделать ячейку плавающей точкой зрения, не можете ли вы понять, как перестроить то, что у вас есть?

2) Итак, вы не решаете предложение 1. Тогда сделайте это. Подумайте о пространстве, используемом табличным представлением, как о представлении контейнера. Всякий раз, когда редактирование таблицы редактируется, сделайте снимок изображения и сохраните это изображение. Как только пользователь начнет прокручивать, поменяйте таблицуViews для изображений. Когда scrollView перестанет заменять UITableView обратно. Это, конечно, займет некоторую точную настройку. Фактически, вы могли бы наложить непрозрачный снимок изображения поверх таблицы (который скроет его и не даст ему попросить сделать сам) во время прокрутки.

Ответ 5

Есть несколько вещей, которые вы можете сделать в целом для повышения производительности табличного представления:

1) Переключитесь на метод Loren Brichter для рисования UITableViewCell (из-за отсутствия лучшей ссылки: http://www.therefinedgeek.com.au/index.php/2010/12/21/fast-scrolling-uitableview-updates-for-ios-4-2/)

В принципе, весь его код делает все содержимое вашей ячейки одним непрозрачным UIView, которое UITableView (и CoreGraphics) может очень быстро взорваться на UITableViewCell

Если вы не хотите делать все свои сотовые проекты в drawRect:, вы все равно можете использовать nibs, но:

  • Удостоверьтесь, что в каждом подзоне отмечен непрозрачный
  • У вас нет прозрачных/полупрозрачных подзонов
  • У вас нет изображений с альфа-каналом!= 1.0f.

2) Не позволяйте UIImageView делать любое масштабирование, чтобы отображать ваше изображение, придать ему UIImage с правильным размером.

3) Если вы используете iOS 5 и выше, вы можете зарегистрировать наконечник для конкретного идентификатора ячейки. Таким образом, когда вы вызываете [tableView dequeueReusableCellWithIdentifier:], вы гарантированно получите ячейку. Распределение ячеек происходит быстрее (согласно Apple), и вы можете писать меньше кода:

- (void)viewDidLoad {
    UINib *nib = [UINib nibWithNibName:@"MyCell" bundle:nil];
    [self.tableView registerNib:nib forCellReuseIdentifier:@"MyCellIdentifier"];
}

// ...

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellIdentifier = @"MyCellIdentifier";
    MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    // Commented out code is no longer needed
    //if (cell == nil) {
    //    cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    //}

    // setup cell

    return cell;
}

4) Отображение изображений, загруженных из Интернета

  • Отображение изображения по умолчанию (что-то, на что можно смотреть при загрузке реального изображения)
  • Запустите загрузку в отдельном потоке (подсказка: используйте GCD dispatch_async())
  • Когда изображение входит, кешируйте его (подсказка: NSCache) и покажите его на ячейке
    • Делает все загрузку/кеширование изображений с основного потока; единственное, что вы должны делать в основном потоке - установить изображение (помните, что код UI должен находиться в основном потоке!)

Вероятно, вы захотите написать UIImageView с поддержкой асинхронного доступа (или использовать существующую библиотеку).

Держитесь подальше от EGOImageView, несмотря на то, что он имеет асинхронную загрузку, он выполняет поиск в кеше (который, случается, находится на диске, так что это означает дорогостоящий диск ввода-вывода) в основном потоке перед отправкой в ​​фоновый поток для загрузки. Я использовал его, но в итоге я написал свой собственный набор классов, чтобы справиться с этим, и это значительно быстрее.

-

Просто следуйте этим инструкциям и напишите здесь другие ppl, и вы увидите таблицы, которые прокручиваются, как стекло, в мгновение ока:)

Ответ 6

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

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

Ответ 7

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

Ответ 8

В то время как 60 FPS - идеальный вариант, игры, такие как Halo, очень хорошо работают в 30 FPS. Хаос в поле битвы, вероятно, предполагает более удивительное, быстрое движение, чем большинство списков, даже сложные, такие как ваши!