调用UIBackgroundTaskIdentifier内的主队列调用

shs*_*hnk 5 objective-c grand-central-dispatch objective-c-blocks uibackgroundtask

我正在运行某项任务,UIBackgroundTaskIdentifier因为我想在后台运行它.我的代码看起来像这样.

-(void) function
{

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

        UIBackgroundTaskIdentifier BGIdentifier = [[UIApplication sharedApplication]   beginBackgroundTaskWithExpirationHandler:^{}];     

        // some processing

        dispatch_async(dispatch_get_main_queue(), ^{
            // some UI stuff
        });

        // some processing again

        dispatch_async(dispatch_get_main_queue(), ^{
            // some UI stuff again
        });

        [[UIApplication sharedApplication] endBackgroundTask:BGIdentifier];        
    });
}
Run Code Online (Sandbox Code Playgroud)

所以我有两个问题.

  1. 如果我的应用程序进入后台,而某些处理正在发生,对主队列的dispatch_async调用会发生什么?
  2. 这是一个很好的设计吗?

Rob*_*Rob 2

在回答您的问题时,那些分派到主队列的块将按照您的预期运行,一切都会正常工作,并且当应用程序返回前台时,您将看到 UI 正确更新。两个注意事项:

  1. 您需要确保endBackgroundTask在最终调度完成之前不会调用 。您可以通过以下任一方式实现此目的:

    • 使最终的 UI 调度同步;或者

    • 将 包含endBackgroundTask为您分派到主队列的最后一个块中的最后一项。

    但这个时间endBackgroundTask很重要,您需要确保在将后台任务标记为完成并指示它可能被挂起之前更新您的 UI。

  2. 我不知道您希望如何处理无法完成后台任务的情况,但通常您也会调用endBackgroundTask过期处理程序,因为否则,如果后台任务未在分配的时间内完成,应用程序将被立即终止。有关示例,请参阅《iOS 应用程序编程指南》的“在应用程序状态和多任务的背景下执行有限长度任务”一章。