Метод iPhone willResignActive не завершает выполнение - PullRequest
2 голосов
/ 14 декабря 2011

Мой делегат приложения должен разблокировать / заблокировать заказ на покупку в моей базе данных Microsoft SQL, когда он входит в фоновый режим или завершается.

Вот мой код

    - (void)applicationWillResignActive:(UIApplication *)application {

    NSLog(@"App will enter background");
    if ([purchaseOrderIsLocked boolValue] && [purchaseOrderAutoID intValue] > 0) {
        NSLog(@"Unlock Purchase Order because app is in background %i", [purchaseOrderAutoID intValue]);
        [self unlockPurchaseOrderWithAutoID:self.purchaseOrderAutoID];
    }   

- (void)applicationWillEnterForeground:(UIApplication *)application {

   NSLog(@"App will enter foreground");

    if ([purchaseOrderIsLocked boolValue] == FALSE && [purchaseOrderAutoID intValue] > 0) {
        NSLog(@"Lock Purchase Order because app is coming back %i", [purchaseOrderAutoID intValue]);
        [self lockPurchaseOrderWithAutoID:self.purchaseOrderAutoID];
    }
}

-(void)lockPurchaseOrderWithAutoID:(NSNumber *)autoID {

NSLog(@"lock purchase order called with autoID=%i",[autoID intValue]);

    self.client = [SqlClientConnect connect];
    [self.client executeQuery:[NSString stringWithFormat:@"UPDATE PURCHASE SET PURCHASELOCK = '9999' WHERE PURCHASEORDERNO = '%i'", [autoID intValue]] 
          withCompletionBlock:^(SqlClientQuery *query) {

              if (query.succeeded) {
                  NSLog(@"locked purchase order");
                  purchaseOrderIsLocked = [NSNumber numberWithBool:YES];
              } else {
                  [self queryFailedWithError:query.errorText]; 
              } 
          }];
}

-(void)unlockPurchaseOrderWithAutoID:(NSNumber *)autoID {
    NSLog(@"unlock purchase order called with autoID=%i",[autoID intValue]);

    self.client = [SqlClientConnect connect];
    [self.client executeQuery:[NSString stringWithFormat:@"UPDATE PURCHASE SET PURCHASELOCK = '0' WHERE PURCHASEORDERNO = '%i'", [autoID intValue]] 
          withCompletionBlock:^(SqlClientQuery *query) {

              if (query.succeeded) {
                  NSLog(@"unlocked purchase order");
                  purchaseOrderIsLocked = [NSNumber numberWithBool:FALSE];
              } else {
                  [self queryFailedWithError:query.errorText]; 
              } 
          }];
   }

}

Хорошо, это выглядит хорошоменя ... однако, когда я запускаю приложение, это то, что я получаю из журнала, когда я нажимаю кнопку "Домой"

    2011-12-14 13:41:20.558 MA Mobile[2267:707] App will enter background
    2011-12-14 13:41:20.558 MA Mobile[2267:707] Unlock Purchase Order
     because app is in background 18 

2011-12-14 13:41:20.559 MA Mobile[2267:707] unlock purchase order called with autoID=18

Он должен был пройти весь путь и опубликовать "разблокированный заказ на покупку", но это не't Когда я возобновляю приложение, это то, что я получаю.

2011-12-14 13: 41: 44.741 MA Mobile [2267: 707] Приложение выйдет на передний план 1 2011-12-14 13: 41: 44.973 MA Mobile [2267: 707] разблокированный заказ на покупку

Это похоже на запуск кода блока после возобновления.Это связано с блоком?Должен ли я сделать что-то другое?

Ответы [ 3 ]

7 голосов
/ 14 декабря 2011

Как только вы выходите из блока и возвращаетесь к -applicationDidResignActive:, ваше приложение немедленно приостанавливается, а запущенный вами асинхронный вызов по существу приостанавливается. Вы должны сообщить приложению, что вам нужно проводить больше времени в фоновом режиме, используя -beginBackgroundTaskWithExpirationHandler: . Вы можете сделать это с помощью кода, как в примере ниже. Для получения дополнительной информации о долгосрочных фоновых задачах см. Фоновое выполнение и многозадачность в Руководстве по программированию приложения для iOS.

Этот простой пример показывает, как использовать эту функцию в вашем коде:

-(void)unlockPurchaseOrderWithAutoID:(NSNumber *)autoID
{
  NSLog(@"unlock purchase order called with autoID=%i",[autoID intValue]);

  // Start long-running background task
  UIBackgroundTaskIdentifier bti = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];

  self.client = [SqlClientConnect connect];
  [self.client executeQuery:[NSString stringWithFormat:@"UPDATE PURCHASE SET PURCHASELOCK = '0' WHERE PURCHASEORDERNO = '%i'", [autoID intValue]] withCompletionBlock:^(SqlClientQuery *query) {
    if (query.succeeded) {
        NSLog(@"unlocked purchase order");
        purchaseOrderIsLocked = [NSNumber numberWithBool:FALSE];
    } else {
        [self queryFailedWithError:query.errorText]; 
    }
    // After we complete the asynchronous block, we need to let the system know we can suspend now
    if( bti != UIBackgroundTaskInvalid )
      [[UIApplication sharedApplication] endBackgroundTask:bti];
  }];
}
1 голос
/ 14 декабря 2011

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

В вашем случае это происходит из-за того, что пользователь нажимает кнопку «Домой», поэтому вызывается этот метод, а затем приложение переходит в фоновый режим, который затем вызывается applicationDidEnterBackground.Здесь вы хотите выполнить этот процесс, по умолчанию, хотя у вас есть всего 5 секунд, чтобы сделать то, что вам нужно.Однако в iOS4 вы можете запросить больше времени, до 10 минут, запустив фоновую задачу.

Ваша реализация этого метода имеет примерно пять секунд для выполнения любых задач и возврата.Если вам требуется дополнительное время для выполнения каких-либо окончательных задач, вы можете запросить дополнительное время выполнения у системы, вызвав beginBackgroundTaskWithExpirationHandler: .На практике вы должны вернуться из applicationDidEnterBackground: как можно быстрее.Если метод не возвращается до истечения времени, ваше приложение завершается и удаляется из памяти.

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

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

Посмотрите в руководстве разработчика iOS раздел «Выполнение задачи длины Fininte в фоновом режиме», чтобы узнать, как можно разрешить вашей задаче запросить дополнительное время для ее выполнения.

...