iOS, прекратить запуск функции при нажатии кнопки «назад» - PullRequest
3 голосов
/ 06 марта 2012

Приложение состоит из видов навигации.Я вызываю функцию в viewDidAppear, которая

[self extractInfoWithWebsite:[NSString stringWithFormat:@"http://www.cineklik.com/%@-%@.aspx", self.cinemaType, self.location]];

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

Проблема в том, что если пользователь решит нажать кнопку «Назад» на панели навигации до этого,информация загружается, страница остается прежней, и приложение перестает функционировать (не происходит сбой, но становится статичным, больше ничего не происходит).

Есть ли решение для этого?Заранее спасибо

РЕДАКТИРОВАТЬ:

Я изменил код на следующее: NSOperationQueue * queue = [NSOperationQueue new];

    /* Create our NSInvocationOperation to call loadDataWithOperation, passing in nil */
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
                                                                            selector:@selector(extractInfoWithWebsite:)
                                                                              object:[NSString stringWithFormat:@"http://www.cineklik.com/%@-%@.aspx", self.cinemaType, self.location]];

    /* Add the operation to the queue */
    [queue addOperation:operation];
    [operation release];

Теперь я могу нажатькнопка возврата без зависания, но теперь происходит сбой со следующей ошибкой: Попытка получить веб-блокировку из потока, отличного от основного потока или веб-потока.Это может быть результатом обращения к UIKit из вторичного потока.Сбой сейчас ... Я думаю, это потому, что моя функция все еще работала в фоновом режиме.Как решить эту проблему?

Ответы [ 4 ]

2 голосов
/ 06 марта 2012

Я бы посмотрел вверх NSOperation

Стандартный подход внутри NSOperation заключается в проверке, были ли они отменены перед выполнением тяжелой обработки.

Здесь - это хорошая ссылка для начала вашего исследования.

РЕДАКТИРОВАТЬ: Я думал, что я бы уточнить, отмененная часть

У операций NSO есть main (), а внутри main () это хорошая практика длясделать что-то вроде

NSData* chunkyReply = nil;

if (!self.isCancelled) {
    chunkyReply = [NSURL stuff];
}    


if (!self.isCancelled) {
    //parse chunkyReply
}
0 голосов
/ 06 марта 2012

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

  • Извлечение данных из URL, который вы 'повторная передача
  • Анализ этих данных

Для первой части, если вы используете [NSData dataWithContentsOfURL:...] или [NSURLConnection sendSynchronoushRequest:returningResponse:error:], вам необходимо изменить их.Ни один из этих двух методов получения URL-адреса не позволяет отменить запрос.Apple имеет хорошую документацию о том, как использовать асинхронные, отменяемые методы.

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

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    //perform parsing
    dispatch_async(dispatch_get_main_queue(), ^{
        if (!self.view.window)
            return; //won't update UI if we've moved offscreen
        //call methods to update the UI
    });
});

Это позволит выполнить синтаксический анализ в фоновой очереди с приоритетом по умолчанию и один раз обновить интерфейс (любые текстовые поля и т. Д.) В основной очереди.синтаксический анализ завершен.

Да, это не может быть отменено, но, как я уже сказал, если вы не обрабатываете много данных, вероятно, безопасно не инкапсулировать анализ вNSOperation.Вы будете тратить немного процессорного времени, но я сначала попробую этот подход, и если производительность не там, где вам нужно, измените на NSOperation позже.Нет смысла в ранней оптимизации, если это не нужно.

0 голосов
/ 06 марта 2012

Существуют различные виды подходов, наиболее подходящий для меня, это инкапсуляция процесса внутри NSOperation , который вы создаете в ViewDidLoad и останавливаете в ViewWillDisappear.

Другой подход - создать объект с делегатом, а затем установить нулевой делегат при выходе из контроллера.

0 голосов
/ 06 марта 2012

Вы можете запустить код загрузки в фоновом режиме, используя:

    [self performSelectorInBackground:<#(SEL)#> withObject:<#(id)#>];

И тогда у вас будет нажатая кнопка «Назад», и вы сможете ее захватить

...