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

Objective-c长时间运行的任务线程混乱,objective-c,multithreading,objective-c-blocks,background-process,long-running-processes,Objective C,Multithreading,Objective C Blocks,Background Process,Long Running Processes,我的应用程序需要执行一些与互联网相关的操作,然后在我将应用程序发送到后台时弹出该视图。然后根视图控制器获取一些数据并更新集合视图。您知道我如何解决与上述操作相关的以下问题吗(顺便说一句,我使用本地通知启动流程): 1) UI相关操作(弹出当前视图控制器)在后台似乎失败 2) 当我将视图弹出到根视图控制器时,根视图有一些nsurlconnection,它将数据发送到它的委托。由于长时间运行的任务在全局队列中运行,nsurlconnection似乎无法向其委托发送任何信息 我在此过程中使用以下代码:

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

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

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

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

另一方面,我想指出,当执行任务的代码完成时,您确实希望调用
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;
    }
});

“与UI相关的操作(弹出当前视图控制器)在后台似乎失败。”如果您在后台,则没有UI。这就是背景中的(部分)含义。你需要重新思考整个架构。谢谢你为我节省了很多时间,伙计。非常抱歉,你错了。调用
endBackgroundTask:
正是您在
beginBackgroundTaskWithExpirationHandler:
中所做的。事实上,这通常是你在那里所做的一切。这个处理程序,如你所知,不是任务,而是如果你的任务在任务的中间过期,你会做什么,并调用<代码> EntReBaseTebug:就是在这种情况下你必须做的事情,或者你的应用程序会在后台被终止。误导OP去相信其他东西是非常糟糕的。OP的代码结构是错误的,但不是按照你所建议的方式。他应该在到期处理程序中和实际任务结束时调用
endBackgroundTask:
。关于一个正确的例子,请参阅我的书:@matt I关注的是,当他的后台任务完成时,他没有调用
endBackgroundTask
(导致后台会话总是超时,这是不必要的),而不是在他真正超时时担心应用程序的状态。我相应地修改了我的答案。谢谢