ios - 设备锁定时后台任务停止?

标签 ios nstimer appdelegate ios8.3

我有一个计时器在设备进入后台时运行,因为我想检查服务中的少量数据。我在应用程序委托(delegate)的 applicationDidEnterBackground 方法中使用以下代码

    UIApplication *app = [UIApplication sharedApplication];

//create new uiBackgroundTask
__block UIBackgroundTaskIdentifier bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    [app endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

//and create new timer with async call:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    //run function methodRunAfterBackground
    NSString *server = [variableStore sharedGlobalData].server;
    NSLog(@"%@",server);
    if([server isEqual:@"_DEV"]){
        arrivalsTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(getArrivals) userInfo:nil repeats:YES];
    }
    else {
        arrivalsTimer = [NSTimer scheduledTimerWithTimeInterval:300 target:self selector:@selector(getArrivals) userInfo:nil repeats:YES];
    }
    [[NSRunLoop currentRunLoop] addTimer:arrivalsTimer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
});

这绝对没问题,直到设备自动锁定,然后计时器停止计时。关于如何阻止这种情况发生的任何建议?默认的实时时间是 5 分钟,因此大多数设备会在这个甚至滴答一次之前很久就被锁定。

谢谢

最佳答案

一些观察:

  1. 正如 H 先生所指出的,beginBackgroundTaskWithExpirationHandler 在现代 iOS 版本中只给您 30 秒(之前是 3 分钟)。因此,尝试在五分钟内启动计时器是行不通的。

    您可以使用 [[UIApplication sharedApplication] backgroundTimeRemaining] 查询您还剩多少时间。

  2. 当设备锁定时,后台任务会继续。您不应该看到应用终止。如果用户通过“双击主页按钮并在任务切换器屏幕上向上滑动”手动终止应用程序,这将终止后台任务,而不是简单地锁定设备。

  3. 关于计时器的一些评论:

    • 代码正在向后台队列添加计时器。这通常是没有必要的。仅仅因为应用程序处于后台状态,您仍然可以继续使用主运行循环来处理计时器等。

      因此,只需从主线程调用 scheduledTimerWithTimeInterval 即可。除非绝对必要,否则用 run loop 耗尽 GCD 工作线程是没有意义的(即便如此,我可能会创建自己的线程并向其添加 run loop)。

      顺便说一句,如果绝对有必要在某些后台调度队列上安排定时器,那么使用调度定时器可能更容易。它完全消除了运行循环要求。

    • 顺便说一句,将scheduledTimerWithTimeIntervaladdTimer 一起使用是不合适的。您调用 scheduledTimerWithTimeInterval 创建一个计时器并将其添加到当前运行循环。您可以使用 timerWithTimeInterval 然后调用 addTimer 如果您想将它添加到另一个运行循环。

关于ios - 设备锁定时后台任务停止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30263427/

相关文章:

UITableViewCell 中的 iOS 输入

ios - 当 View Controller 向后导航到时重新加载表

ios - 调用函数一段时间然后调用另一个函数 - NSTimer

ios - 当应用进入后台时暂停 NSTimer

ios - 检查 AppDelegate 中 session 中的用户,如果没有则触发 UIViewController

ios - 加载用户文件的所有路径时,Dropbox 错误 400 invalid_request

ios - NSString 到 SecKeyRef

ios - 应用程序中的自动注销计时器?

ios - 我有多个 Storyboard。如何使用 AppDelegate 在另一个 Storyboard中打开另一个 ViewController? (继续)

iOS 11 应该通过 App Delegate 方法或仅通过 UNDelegate 方法处理推送通知