#objective-c #ios #uiview #uiscrollview
#objective-c #iOS #uiview #uiscrollview
Вопрос:
В Microsoft Outlook раньше был — и, возможно, все еще есть — просмотр временной шкалы прокрутки всех действий, выполненных в Outlook. Я хотел бы воссоздать что-то подобное в своем приложении.
Я изучил документацию для UIScrollView и знаю, как заставить ее работать так, как я хочу. Мой вопрос больше ориентирован на наиболее эффективный способ представления нескольких сотен элементов в UIScrollView, когда представление содержимого, вероятно, будет большим.
Я мог бы:
- Соберите список меньших представлений, каждое из которых представляет, например, день, и заполните эти меньшие представления элементами данных за каждый из этих дней, а затем добавьте эти совокупные представления в качестве вспомогательных представлений в представление содержимого.
или
- Я мог бы просто заполнить представление содержимого вспомогательными представлениями для каждого из элементов данных, которые я хочу отобразить на временной шкале.
Что я хочу выяснить, так это:
- Какой наиболее эффективный способ, с точки зрения памяти и времени, представить все эти точки данных? Каждая из них будет отображаться на временной шкале в виде метки или кнопки.
- Какой метод более естественным образом поддерживает сжатие и масштабирование?
- Лучше ли заранее инициализировать весь просмотр содержимого (и, возможно, потратить много времени), или лучше просто инициализировать представление вблизи «окна просмотра», а затем добавлять детали по мере прокрутки пользователем?
Спасибо!
Ответ №1:
Единственный способ узнать наверняка — это немного поэкспериментировать. Я понимаю, что это не слишком полезный ответ, но я могу, по крайней мере, дать вам несколько советов:
Эффективное отображение более чем одного экрана с UIScrollView
s, как известно, сложно. В некоторых случаях я боролся с этим неделями. Это было намного хуже на более старом оборудовании (iPhone 3G / iPod 2-го поколения или старше), но вы все равно можете легко выполнить обход современных устройств iOS, если вы ошибаетесь. Обычно вы сталкиваетесь с двумя проблемами производительности:
- Одновременное отображение многих
UIView
символов (включая UILabel и т.д.) На экране серьезно снижает производительность. Вы столкнетесь с этим, если каждая точка данных является представлением, и вы можете уменьшить масштаб, чтобы увидеть их все. - И наоборот, иметь огромные представления (больше одного экрана) одинаково плохо, поскольку все представление должно храниться в памяти, пока что-либо из него видно.
Вы, вероятно, можете видеть, как это плохо сочетается с масштабированием: вы не знаете точно, сколько занимает один экран!
- Я предлагаю вам для начала настроить все красиво и просто, используя все в качестве представлений, и не слишком беспокоиться о масштабировании — убедитесь, что все работает плавно на максимальном уровне масштабирования.
- Затем добавьте масштабирование (вам нужно поместить все ваши маленькие представления в один вид контейнера, который будет увеличен) и посмотрите, как это работает на вашем самом старом поддерживаемом оборудовании. Если вы не разрешаете слишком сильно уменьшать масштаб, все может быть в порядке без каких-либо изменений.
- Если при уменьшении масштаба он начинает пыхтеть, попробуйте разделить содержимое на плитки. Вам нужно будет поэкспериментировать с их размером, но 20 подвидов на плитку, вероятно, хорошее начало. В вашем делегате просмотра прокрутки определите, когда пользователь достаточно уменьшен, и принудительно растрируйте ваши плитки, установив для
shouldRasterize
свойства значение true для ихCALayer
. По сути, это должно привести к предварительному рендерингу всех подвидов плиток в текстуру, поэтому, когда дело доходит до рендеринга экрана, он будет использовать это предварительно отрисованное изображение вместо того, чтобы просматривать все ваши подвиды и рендерить их по отдельности. Обязательно отключите его снова, как только пользователь снова увеличит масштаб изображения в достаточной степени. Также старайтесь не устанавливать его для всех плиток сразу, иначе он будет заикаться, так что, например, вы могли бы установить отдельные пороговые значения уровня случайного масштабирования для каждой плитки.
Если в конечном итоге у вас возникнут проблемы с shouldRasterize
, вам может потребоваться работать на CALayer
уровне напрямую. Если ничего из этого не помогает, следует использовать метод sledgehammer, CATiledLayer
как MKMapView
и другие. Это требует, чтобы вы сами выполняли весь рендеринг и обработку событий касания, и обычно также вызывает (несколько уродливое) затухание, которое вы получаете при прокрутке в приложениях Maps и Safari.
Некоторые дополнительные подсказки:
- Избегайте хранения большого количества разных изображений в памяти. Это означает повторное использование небольшого количества
UIImage
s, если вы можете. Если каждый вид немного отличается, сгенерируйте изображения по запросу в drawRect: или используя фильтры, а не рисуйте их какCGImage
s заранее или загружайте их из файла. - Избегайте альфа-смешивания (прозрачности), если это вообще возможно.
- Вы можете визуализировать сложность компоновки UIKit с помощью инструмента Performance. Ознакомьтесь с основными докладами по анимации и инструментам из архивов WWDC.
Я надеюсь, что это поможет вам начать. Удачи!
Комментарии:
1. Вау, это фантастическая информация, и именно то, что я искал. Большое вам спасибо за хорошо написанный ответ.