iPhone将使用ResignActive方法无法完成执行

时间:2011-12-14 18:59:13

标签: iphone objective-c objective-c-blocks

我的应用代理需要在我的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

它应该已经完成​​并发布了“未锁定的采购订单”,但事实并非如此 当我恢复应用程序时,这就是我得到的。

  

2011-12-14 13:41:44.741 MA Mobile [2267:707]应用程序将进入前台   1 2011-12-14 13:41:44.973 MA Mobile [2267:707]解锁采购订单

它就像恢复后运行块代码一样。这与块有关吗?我应该做些不同的事吗?

3 个答案:

答案 0 :(得分:7)

一旦您离开该区块并返回-applicationDidResignActive:,您的应用程序会立即暂停,您启动的异步通话基本上会暂停。您需要让应用程序知道您需要使用-beginBackgroundTaskWithExpirationHandler:在后台花更多时间。您可以使用以下示例中的代码执行此操作。有关长时间运行的后台任务的更多信息,请参阅iOS应用程序编程指南中的Background Execution and Multitasking

这个简单的示例演示了如何在代码中使用此功能:

-(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 :(得分:1)

applicationWillResignActive非常快,因此在应用程序丢失前景之前,您的任务很可能没有完成。此方法与某些具有相似名称的其他方法不同。系统不会询问您是否可以让应用程序辞职,而是告诉您应用程序现在正在重新签名。

查看iOS Developer guide有关“在后台执行Fininte长度任务”部分,了解如何让您的任务要求额外的时间来完成。

答案 2 :(得分:1)

applicationWillResignActive可以提供信息,告诉您您的应用程序不再可用于接收用户交互,例如在收到呼叫或弹出系统警报时。

在您的情况下,这是因为用户点击了主页按钮,因此调用此方法,然后您的应用程序将进入后面调用applicationDidEnterBackground的背景。这是您要执行此过程的位置,默认情况下,您只需要5秒钟即可完成所需操作。但是在iOS4中,您可以通过开始后台任务请求更多时间,最多10分钟。

  

您执行此方法大约需要五秒钟才能执行任何任务并返回。如果您需要额外的时间来执行任何最终任务,可以通过调用beginBackgroundTaskWithExpirationHandler:从系统请求额外的执行时间。实际上,您应该尽快从applicationDidEnterBackground返回:如果方法在时间用完之前没有返回,则应用程序将终止并从内存中清除。