0

Моему приложению нужно выполнить некоторую операцию, связанную с Интернетом, а затем просмотреть этот вид, когда я отправлю приложение на задний план. А затем контроллер корневого представления извлекает некоторые данные и обновляет представление коллекции. Есть ли у вас какие-либо идеи, как я могу решить следующие проблемы, связанные с вышеуказанными операциями (кстати, я использую локальные уведомления для запуска процесса):Objective-c Long Running Task Thread Confusion

1) Операции, связанные с интерфейсом UI (контроллер текущего текущего вида), как представляется, задний план.

2) Когда я выхожу из вида на контроллер корневого представления, в корневом представлении есть некоторое nsurlconnection, которое отправляет данные своему делегату. Поскольку длинные запущенные задачи выполняются в глобальной очереди, nsurlconnection, похоже, не отправляет какую-либо информацию своему делегату.

Я использую следующий код для этого процесса:

UIBackgroundTaskIdentifier __block bgTask; 
    UIApplication *app = [UIApplication sharedApplication]; 
    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
     [app endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    }]; 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     [self performOperation]; 
     NSLog(@"Operation finished"); 
    }); 
+0

«операции, связанные с UI (выскакивают текущий контроллер представления), кажется, не в состоянии в фоновом режиме.» Если вы находитесь в фоновом режиме, у вас нет пользовательского интерфейса. Это (часть), что значит быть на заднем плане. Вам нужно переосмыслить всю эту архитектуру. – matt

+0

Спасибо, что спасли меня много часов. – user1433743

ответ

-1

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

Я предполагаю, что наблюдение мата отвечало на ваш второй вопрос. Если это не так, пожалуйста, уточните, что вы имеете в виду. Но это использование UIBackgroundTaskIdentifier не волнует, использовали ли вы глобальные очереди или пользовательские очереди или что-то еще. Единственное ограничение состоит в том, что некоторые операции пользовательского интерфейса не будут выполняться, поэтому ничего, зависящее от, например, viewDidAppear, не будет.

Как в стороне, я хотел бы указать, что вы действительно хотите позвонить endBackgroundTask, когда код, выполняющий задачу, завершается, что ваш образец кода не работает. См. Executing a Finite-Length Task in the Background из Состояние приложений и многозадачность глава руководства по программированию приложений для iOS .

Таким образом, вы могли бы сделать что-то вроде:

UIApplication *app = [UIApplication sharedApplication]; 

UIBackgroundTaskIdentifier __block bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
    NSLog(@"Operation did not finish!!!"); 

    [app endBackgroundTask:bgTask]; 
    bgTask = UIBackgroundTaskInvalid; 
}]; 

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    [self performOperation]; 
    NSLog(@"Operation finished"); 

    if (bgTask != UIBackgroundTaskInvalid) { 
     [app endBackgroundTask:bgTask]; 
     bgTask = UIBackgroundTaskInvalid; 
    } 
}); 
+0

Мне очень жаль, но вы просто ошибаетесь. Вызов 'endBackgroundTask:' _exactly_, что вы делаете в 'beginBackgroundTaskWithExpirationHandler:'. В самом деле, вы обычно это делаете. Этот обработчик выражает, как вы знаете, не задачу, а то, что вы будете делать, если ваше время истекает в середине задачи - и вызов 'endBackgroundTask:' именно то, что вы должны сделать в этом случае, или ваше приложение будет суммировано завершено в фоновом режиме. Было бы очень плохо ввести ОП в заблуждение. – matt

+0

Структура кода OP неверна, но не так, как вы предлагаете. Он должен вызывать 'endBackgroundTask:' _both_ в обработчике истечения _and_ в конце фактической задачи. Для правильного примера см. Мою книгу: http://www.apeth.com/iOSBook/ch38.html#_threads_and_app_backgrounding – matt

+0

@matt Я фокусировал внимание на том, что он не вызывал «endBackgroundTask», когда закончилась его фоновая задача (вызывая фоновый сеанс всегда тайм-аут, без необходимости), и не беспокоиться о состоянии приложения, когда у него был подлинный тайм-аут. Я соответствующим образом пересмотрел свой ответ. Благодаря! – Rob