如何使用beginBackgroundTaskWithExpirationHandler在iOS版已

2019-06-17 19:41发布

在我的应用程序,我从iPhone上传图片到服务器。 虽然同步如果用户按Home键,应用程序将关闭。

我想要的应用程序必须在后台,直到同步完成运行。

我的问题是:我怎样才能加目前正在运行的“任务beginBackgroundTaskWithExpirationHandler ”?

请分享你的想法。

Answer 1:

尽管它的名字, beginBackgroundTaskWithExpirationHandler:实际上并没有“开始”的任务。 这可能是更好的思想为“注册...”,而不是“开始......”你只是告诉你在做的事情想完成,如果这是确定的,中间是该系统。

几点:

  • 在几乎所有情况下,你要调用beginBackgroundTaskWithExpirationHandler:当你开始做你想要做的事,然后endBackgroundTask:当你完成。 你几乎从来没有在用户按下Home键(除非这就是问题所在,当你开始任务,如保存一些东西到服务器)点调用这些。

  • 你可以有很多“后台任务”,只要你想在同一时间打开。 他们没有成本。 他们就像保留计数。 只要你仍然有一个开放的(一个“开始”没有获得其“结束”),则系统会认为,为更多时间的请求。 有成本很少调用“开始”和“结束”的方法,所以使用这些括号要额外的时间来完成任何事情。

  • 有没有办法可以肯定,你会得到完成你同步。 这些方法只是做一个请求。 操作系统可能仍然拒绝这一请求。 操作系统仍然随时可能杀了你,它需要一些额外的资源。 该操作系统是不是无限耐心; 如果你花费太长时间(约10分钟,通常),它会调用您的到期处理后反正杀了你。 因为手机被关闭,操作系统可能会杀了你。 你的应用必须能够处理没有得到完成。 操作系统只是给你这种能力,这样就可以改善用户体验。



Answer 2:

我用下面的后台任务处理程序代码:

__block UIBackgroundTaskIdentifier backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{

    NSLog(@"Background Time:%f",[[UIApplication sharedApplication] backgroundTimeRemaining]);

    [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier];

    backgroundTaskIdentifier = UIBackgroundTaskInvalid;
}];


Answer 3:

以下是我用beginBackgroundTaskWithExpirationHandler,包括调用该方法在后台完成。 这包括用于启动新的异步任务的代码。 所以,不正是在此提出问题。 添加以下代码,想有人可能会寻找这样的情景:

- (void)didReceiveObjList:(CFDataRef)message
{
  // Received Object List. Processing the list can take a few seconds.
  // So doing it in separate thread with expiration handler to ensure it gets some time to do     the task even if the app goes to background.

  UIApplication *application = [UIApplication sharedApplication];
  __block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
    [application endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      [self processObjList:message];

    [application endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
  });

  NSLog(@"Main Thread proceeding...");

}


Answer 4:

看看这个页面中,苹果描述了如何保持iPhone应用程序没有中止,而它在后台。 苹果文档

这里就是我实现:

UIBackgroundTaskIdentifier bgTask;

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    NSLog(@"=== DID ENTER BACKGROUND ===");
    bgTask = [[UIApplication  sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        NSLog(@"End of tolerate time. Application should be suspended now if we do not ask more 'tolerance'");
        // [self askToRunMoreBackgroundTask]; This code seems to be unnecessary. I'll verify it.
    }];

    if (bgTask == UIBackgroundTaskInvalid) {
        NSLog(@"This application does not support background mode");
    } else {
        //if application supports background mode, we'll see this log.
        NSLog(@"Application will continue to run in background");  
    }
}

/*

- (void)askToRunMoreBackgroundTask
{
    [[UIApplication sharedApplication] endBackgroundTask:bgTask];
    NSLog(@"restart background long-running task");
    bgTask = [[UIApplication  sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        NSLog(@"End of tolerate time. Application should be suspended now if we do not ask more 'tolerance'");
        [self askToRunMoreBackgroundTask]; 
    }];

}

*/

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    NSLog(@"=== GOING BACK FROM IDLE MODE ===");
    //it’s important to stop background task when we do not need it anymore
    [[UIApplication sharedApplication] endBackgroundTask:UIBackgroundTaskInvalid];  
}


Answer 5:

下面是关于当应用程序会在后台,我需要做一些事情的主线上,我正在使用其他的答案稍有不同:

- (void)applicationWillResignActive:(UIApplication *)application
{
     UIApplication *app = [UIApplication sharedApplication];

    // Register auto expiring background task
    __block UIBackgroundTaskIdentifier bgTaskId =
        [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTaskId];
        bgTaskId = UIBackgroundTaskInvalid;
    }];

    // Execute background task on the main thread
    dispatch_async( dispatch_get_main_queue(), ^{
        // ------------------
        // DO SOMETHING INVOLVING THE WEBVIEW - WHICH MUST OCCUR ON THE MAIN THREAD!
        // ------------------
        [app endBackgroundTask:bgTaskId];
        bgTaskId = UIBackgroundTaskInvalid;
    });
}


Answer 6:

您应该运行后,你的任务beginBackgroundTaskWithExpirationHandler或捕获通知时,应用程序更改应用的状态,背景,然后取消当前的任务,并再次运行beginBackgroundTaskWithExpirationHandler



文章来源: How to use beginBackgroundTaskWithExpirationHandler for already running task in iOS