RunLoop с блокировкой UITableView - PullRequest
       0

RunLoop с блокировкой UITableView

0 голосов
/ 15 декабря 2011

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

У меня есть UITableView с элементами, при щелчке по элементу он выходит в Интернет, выбирает этот элемент и отображает его. Остальная часть программы (не показана) будет использовать загруженный элемент, поэтому одновременно можно загрузить только один элемент.

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

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

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

  1. Когда пользователь нажимает на ячейку таблицы, вызывается didSelectRowAtIndexPath, там я устанавливаю глобальный флаг, а затем вызываю метод загрузки для загрузки элемента. Если пользователь нажимает на другой элемент (до завершения загрузки, он увидит установленный флажок и выйдет из этой функции, не загружая ничего. В основном это:

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        static BOOL alreadyInHere=FALSE;
        if (alreadyInHere) return;
        alreadyInHere=TRUE;
        ....
        downloadItem(...);
        ShowAndUseItem(...);
        alreadyInHere=FALSE;
    }
    

    Это позволяет пользователю выбирать только один элемент за раз.

  2. Чтобы позволить пользователю иметь возможность прокручивать UITableView во время длительной загрузки, я включил цикл выполнения в методе downloadItem (...), показанном выше, как это ...

    -(void) downloadItem(....)
    {
        BOOL downloading=TRUE;
        callFunctionsToStartdownload(...); //
        while (downloading) {
            downloading=DownloadSomeBytes(...);  
            CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.5, YES);
        }
    }
    

Результатом (1) и (2) является то, что пользователь все еще может прокручивать UITableView во время последовательной загрузки, флаг readyInHere не позволяет ему выбрать что-либо и начать другую загрузку.

В большинстве случаев это работает, но примерно в 50% случаев во время загрузки UITableView перестает отвечать на запросы (не может перейти к другим элементам в таблице), и даже после загрузки didSelectRowAtIndexPath больше не вызывается, когда вы нажмите на что-нибудь, что сделает UITableView в основном заблокированным.

У меня вопрос, правильно ли я выполнил runLoop?

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

Спасибо

1 Ответ

1 голос
/ 15 декабря 2011

Вы не должны пытаться загружать или выполнять какие-либо другие потенциально длительные действия в методе youR tableview didSelectRow.Выйдите (вернитесь) из этого метода пользовательского интерфейса после настройки асинхронной загрузки, чтобы не блокировать пользовательский интерфейс.

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

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