2011-12-14 9 views
0

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

У меня есть 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 во время последовательной загрузки, флаг isinere запрещает им что-то выбирать и запускать другую загрузку.

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

Мой вопрос: правильно ли я выполняю runLoop?

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

Благодаря

+2

Это ужасный способ сделать это. Каковы ваши «другие причины»? –

+0

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

ответ

1

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

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

+0

+1 iOS обеспечивает надежные механизмы для асинхронных загрузок именно по этой причине. Если у вас есть протокол, отличный от HTTP, вы видите CocoaAsyncSocket для отличной основы для обработки произвольных сетевых протоколов. –

+0

О, извините, это был старый код. Вот как это работает в настоящее время –

+0

- (void) downloadItem (....) { BOOL downloading = TRUE; callFunctionsToStartdownload (...); // while (загрузка) { downloading = DownloadSomeBytes (...); CFRunLoopRunInMode (kCFRunLoopDefaultMode, 0,5, YES); }} –

Смежные вопросы