Objective-c Долгосрочная задача

Моему приложению нужно выполнить некоторые операции, связанные с Интернетом, а затем открыть это представление при отправке приложения в фоновом режиме. Затем контроллер корневого представления извлекает некоторые данные и обновляет представление коллекции. Есть ли у вас какие-либо идеи, как я могу решить следующие проблемы, связанные с вышеуказанными операциями (кстати, я использую локальные уведомления, чтобы начать процесс):

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

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");
     });

1 ответ

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

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

Кроме того, я хотел бы отметить, что вы действительно хотите позвонить endBackgroundTask когда код, выполняющий задачу, завершается, что, по-видимому, не делает ваш пример кода. См. Раздел " Выполнение задачи конечной длины" в главе " Состояния приложений и многозадачность" в Руководстве по программированию приложений для 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;
    }
});