Objective-c长时间运行任务线程混乱

时间:2014-01-29 19:50:06

标签: objective-c multithreading objective-c-blocks background-process long-running-processes

我的应用程序需要执行一些与互联网相关的操作,然后在将应用程序发送到后台时弹出该视图。然后根视图控制器获取一些数据并更新集合视图。您是否知道我如何解决与上述操作相关的以下问题(顺便说一下,我使用本地通知来启动该过程):

1)UI相关操作(弹出当前视图控制器)似乎在后台失败。

2)当我将视图弹出到根视图控制器时,Root视图有一些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 个答案:

答案 0 :(得分:-1)

正如matt指出的那样,当应用程序在后台时,你无法执行UI操作,例如弹出视图控制器。当应用程序返回到前台时(例如,用户再次点击图标),则可能会发生弹出(如果应用程序未在此期间完全终止)。

我认为亚马的观察回答了你的第二个问题。如果没有,请澄清你的意思。但是UIBackgroundTaskIdentifier的这种使用并不关心你是使用全局队列还是自定义队列或其他什么。唯一的限制是不会发生某些UI操作,因此不会发生任何意外情况,例如viewDidAppear

顺便说一句,我想指出,当执行任务的代码完成时,您真的想要调用endBackgroundTask,而代码示例似乎没有这样做。请参阅 iOS应用程序编程指南的应用程序状态和多任务章节的Executing a Finite-Length Task in the Background

因此,您可以执行以下操作:

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