Как я могу прокручивать UIView неопределенного размера в UIScrollView

Я пытаюсь нарисовать график, который бесконечно большой по горизонтали и имеет ту же высоту, что и экран. Я добавил UIScrollView и подкласс UIView внутри него, который реализует метод -drawRect:. В симуляторе все работает нормально, а вот на устройстве не получается отрисовать график после достижения им определенного размера.

Я уже кэширую почти все, что могу, и в основном вызываю CGContextAddLineToPoint только в разделе -drawRect:. Я рисую только то, что видно на экране. У меня есть делегат UIScrollView, который прослушивает -scrollViewDidScroll:, который затем сообщает графику о перерисовке себя ([graphView setNeedsDisplay]).

Я нашел один метод, который говорит мне переопределить метод +layerClass и вернуть [CATiledLayer class]. Это действительно позволяет графу рисовать на устройстве, но работает очень плохо. На самом деле рисовать невероятно медленно, и возникающее затухание нежелательно.

Какие-либо предложения?


person Ed Marty    schedule 22.12.2008    source источник


Ответы (4)


Что ж, вот мой ответ: я в основном сделал что-то похожее на то, как UITableView работает с ячейками: у меня есть NSMutableSet объектов GraphView, в которых хранятся неиспользуемые графики. Когда часть представления прокрутки становится видимой, я беру графическое представление из этого набора (или создаю новый, если набор пуст). У него уже было свойство scrollX для определения того, какая его часть должна быть отрисована. Я установил для свойства scrollX правильное значение и вместо использования ширины экрана задал произвольную ширину для рисования. Когда он выходит из режима прокрутки, он удаляется из UIScrollView и добавляется в набор.

Интересно, действительно ли мне нужно удалять их, когда они выходят из поля зрения? Может быть, стоит попробовать оставить их и удалить те, которых нет на экране, только если я получу предупреждение о нехватке памяти? Это может избавиться от паузы всякий раз, когда необходимо перерисовать участок графика, который не изменился.

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

person Ed Marty    schedule 24.12.2008

Я думаю, что это ограничение графического оборудования iPhone. Путем экспериментов я увидел, что iPhone отказывается рисовать кадр размером более 2000 пикселей как по высоте, так и по ширине. Вероятно, это как-то связано с ограниченным размером буфера кадров в аппаратном обеспечении.

person Marc Novakowski    schedule 22.12.2008
comment
Не очень полезный ответ, я думаю. Очевидно, есть способ сделать это, поскольку такие вещи, как Google Maps, похоже, работают нормально. Совсем не прерывистый и, кажется, довольно быстро рисует, даже когда сначала нужно загрузить данные. - person Ed Marty; 22.12.2008
comment
Я просто говорю, что вы не можете сделать это в рамках одного элемента управления пользовательского интерфейса, потому что его рамка будет слишком большой. Вероятно, вы можете разместить несколько представлений вместе по горизонтали, но вам, вероятно, придется управлять ими самостоятельно (уничтожая/создавая на лету). - person Marc Novakowski; 22.12.2008

Посмотрите видео сеанса WWDC 2011 года под названием «Сеанс 104 — Расширенные методы просмотра прокрутки».

person EricS    schedule 04.07.2011

Спасибо, это полезно. Один вопрос - что вы использовали для contentSize UIScrollView? Допускает ли UIScrollView большие размеры содержимого (более 2000 пикселей), если вы не создаете буферы для заполнения всего пространства в представлении содержимого? Или вы сохраняете UIScrollView постоянным размером (скажем, 2 ширины экрана) и оставляете свойство UIScrollView contentOffset каждый раз, когда рисуете (используя scrollX вместо contentOffset для хранения вашей позиции)?

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

person Community    schedule 28.04.2009
comment
ContentSize настолько велик, насколько это необходимо (до 50500 пикселей в моем случае), с множеством разных представлений внутри него. - person Ed Marty; 28.04.2009
comment
Вы экспериментировали с хранением только объектов CGLayer и CGPoint для каждого кеша вместо всего представления? Я думаю, что это уменьшит накладные расходы, но я не уверен, что это будет иметь большое значение. - person ; 29.04.2009
comment
Если подумать, это не сработает, потому что CGLayer нужно отрисовывать в каком-то контексте, поэтому вам все равно нужен UIView для отрисовки. Неважно. - person ; 29.04.2009