【问题标题】:iOS: Repeated task only when APP is active (No background)iOS:仅在 APP 处于活动状态时重复任务(无背景)
【发布时间】:2014-03-26 22:00:47
【问题描述】:

我找到了几个post 询问如何运行后台任务。这可以。我知道了。有一个来自 Apple 的 guideline,只能用于某些类型的应用程序。

我的用例如下:我只想在聊天应用处于前台时更新联系人列表。因此,当应用程序分别进入以下状态时,我可以启动/暂停/恢复:didBegan、didEnterBackground、didResumeFromBackground。

如何使用 GCD 实现这一目标?

换句话说,我怎样才能以重复的方式安排一个异步任务,并且只每隔一段时间(比如每 0.5 秒)调用一次?使用 NSOperationQueue 有好的实现吗?

编辑 2:我要执行的任务:

1:从 Web 服务 API 获取一个 JSON 数据对象,其中包含有关联系人的信息(在线状态、设备、上次访问时间)

2:从 Web 服务 API 获取一个 JSON 数据对象,其中包含发送给用户的消息

编辑:NSOperation 文档将操作定义为只能用作“单次”的操作,因此创建递归操作可能不是解决此问题的最佳方法。

【问题讨论】:

  • 嗯?递归操作?您可以使用块创建操作,它的行为与调度队列完全相同。
  • @LeoNatan 我在 cmets 中看到了你的观点。我会试试你的方法。所以基本上 NSTimer 对象仅在应用程序在前台而不是在后台并且有自己的内部恢复/挂起方法正确时执行?
  • 是的。当应用程序进入后台时,计时器会暂停。当它返回前台时,计时器将恢复,任何到期的计时器都会触发。对此的一个警告是,您的应用程序可能会在后台唤醒(例如,来自推送)。当应用程序运行时,计时器也会在后台运行。
  • @LeonNatan 谢谢。不一样但相关:当APP进入后台时,调度队列会发生什么?队列是否暂停然后恢复?如果没有,如果任务还没有到达区块会发生什么?换句话说,如果我调用“dispatch_async(server_queue, ^{block})”,是否总是会到达 block
  • 整个应用程序被挂起,所以是的,调度队列和操作队列都被挂起。如果您已将任务或操作排入队列,它将在系统恢复后触发(当应用程序进入前台或恢复在后台运行时)。

标签: ios iphone objective-c grand-central-dispatch nsoperationqueue


【解决方案1】:

这里是一些关于如何使用计时器以及 GCD 和操作队列来实现此目的的代码。

NSOperationQueue* queue = [NSOperationQueue new];
[queue setMaxConcurrentOperationCount:1]; //Make serial.
//dispatch_queue_t queue = dispatch_queue_create("queue", NULL); //Serial queue.

先生们,开始你的计时器:

[NSTimer scheduledTimerWithTimeInterval:0.0 target:appDelegate selector:@selector(timerTicked:) userInfo:nil repeats:NO]; //Start a timer with 0 so it ticks immediately.

现在在方法中:

- (void)timerTicked:(NSTimer*)timer
{
    NSLog(@"Timer ticked!");
    void (^block)() = ^{
        //Do what you need here.

        //Start a new timer.
        [NSTimer scheduledTimerWithTimeInterval:1.0 target:appDelegate selector:@selector(timerTicked:) userInfo:nil repeats:NO];
    };

    [queue addOperationWithBlock:block];
    //dispatch_async(queue, block);
}

我使用应用程序委托是因为计时器保留了目标对象,所以我不想将它放在视图控制器中。您可以在计时器滴答之后或操作/任务完成之后安排下一个计时器,这是我更喜欢做的事情。

【讨论】:

  • 太棒了。非常感谢。抱歉,重复的问题和 cmets :-)。希望我能给 +5 票,因为它非常有用。
【解决方案2】:

使用 NSTimer 安排每 0.5 秒触发一次的计时器。它可以将您的 NSOperation 添加到 NSOperationQueue。您可能想要创建一个最大并发数为 1 的特殊队列,因此它一次只会运行您的一件事情。您可能还想在添加新操作时取消所有以前的操作,以防万一事情开始“堆积”。我不知道你的具体任务是什么,所以很难更准确。

【讨论】:

  • 太棒了。这听起来很棒。我马上试试。
  • @mm24 关于计时器的一句话。如果您将计时器设置为重复,则在来自后台后可能会发生不良影响,其中计时器可能会触发多次(如果它有机会运行,它会触发的次数)。更好的方法是将计时器安排为不重复,并在旧的处理程序完成其任务后安排新的计时器。
  • @jsd 我在答案中添加了一个特定的用例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多