Как заставить пользовательский интерфейс реагировать постоянно и выполнять фоновое обновление? - PullRequest
2 голосов
/ 27 февраля 2011

Я создаю приложение, которое отображает 8 миниатюр на страницу и может иметь n страниц. Каждая из этих миниатюр представляет собой UIViews и добавляется в UIScrollView. Однако я реализовал пейджинг с использованием примера кода Apple.

Проблема:

  1. Каждый эскиз (UIView) занимает 150 миллисекунды, которые будут созданы и добавлены в просмотр прокрутки
  2. Следовательно, для 3 страниц это ужасно огромное время, которое будет создано и добавлено в Scrollview пользовательского интерфейса.
  3. На этом этапе представление прокрутки не очень отзывчиво, оно очень резкое и дает плохой пользовательский опыт
  4. Как я могу создать миниатюры и добавить их в UIScrollview, не влияя на реакцию сенсорного экрана? Я хочу, чтобы они работали независимо от основного потока, который отвечает за обработку сенсорных событий (я полагаю).

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

Дайте мне знать, какие опции у меня есть, чтобы сделать его более отзывчивым, и обновляйте пользовательский интерфейс, не затрагивая сенсорные операции. Элемент управления страницы отлично работает с ленивой загрузкой сетки миниатюр.

ТИА

Правин С

Ответы [ 3 ]

10 голосов
/ 01 марта 2011

Grand Central Dispatch прост в использовании для фоновой загрузки. Но GCD только для после iOS4. Если вам требуется поддержка iOS3, выполните executeSelectorInBackground / executeSelectorOnMainThread или NSOperationQueue.

И, будьте осторожны, почти классы UIKit не являются поточно-ориентированными, за исключением рисования в графическом контексте. Например, UIScrollView не является поточно-ориентированным, UIImage imageNamed: не является поточно-безопасным, но UIImage imageWithContentsOfFile: является поточно-ориентированным.

dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_queue_t concurrentQueue =
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(concurrentQueue, ^{

    dispatch_apply([thumbnails count], concurrentQueue, ^(size_t index) {

        Thumbnail *thumbnail = [thumbnails objectAtIndex:index];
        thumbnail.image = [UIImage imageWithContentsOfFile:thumbnail.url];

        dispatch_sync(mainQueue, ^{

            /* update UIScrollView using thumbnail. It is safe because this block is on main thread. */

        });
    }

    /* dispatch_apply waits until all blocks are done */

    dispatch_async(mainQueue, ^{
        /* do for all done. */
    });
}
0 голосов
/ 16 февраля 2012

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

В частности, пример с яблокомкод для scrollview с pagecontrol имеет что-то вроде этого:

[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];

Однако этот код появляется в их примере в методе "scrollViewDidScroll".Он пытается выполнить несколько тяжелых работ одновременно с помощью прокрутки и загрузки.Даже если ваши изображения являются локальными, это неприятно.

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

0 голосов
/ 27 февраля 2011

У меня была похожая проблема.
В одном случае я сохранил только 3 страницы в памяти и очистил оставшиеся все.
Если предположить, что есть 3 экрана s1, s2, s3. И пользователь просматривает s2. Всякий раз, когда он переходит к s3, я удаляю s1 и загружаю новую страницу s4.
Так что пользователи будут иметь лучший опыт. И меньше памяти будет занято.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...