具有NSTimers和服务器调用的后台模式

时间:2016-01-19 21:53:08

标签: ios objective-c nstimer background-process

我正在使用一个sdk,它使用NSTimer在x分钟到期时进行服务器调用,服务器调用在完成一些工作后将计时器重置为x分钟。我遇到的问题是我的计时器在我的应用程序处于后台时停止运行,并在我的应用程序回到前台时立即恢复。我如何让它工作?

//initialize self.myTimer somewhere in my code
//called once somewhere in my code-->[self resetTimer:self.myTimer expiry:30];

- (void)resetTimer:(NSTimer *)timer expiry:(float)seconds {
[timer invalidate];
NSTimer *newTimer = [NSTimer timerWithTimeInterval:seconds
                                            target:self
                                          selector:@selector(updateTimer:)
                                          userInfo:nil
                                           repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:newTimer forMode:NSRunLoopCommonModes];

self.myTimer = newTimer;

}

- (void) updateTimer:(NSTimer *)timer {

    [timer invalidate];

    dispatch_queue_t queue = dispatch_queue_create("update", NULL);
    dispatch_async(queue, ^{
    [self serverCall];
    });
}

-(void)serverCall{
//make server call and do some work
[self resetTimer:self.myTimer expiry:30];


}

1 个答案:

答案 0 :(得分:3)

当应用在后台时,计时器不会继续触发。如果您愿意让操作系统设置服务器调用的速度,您可以通过查阅此background execution doc中的“有机会获取少量内容”部分来完成此操作。

要点是在info.plist中设置应用的UIBackgroundModes键== fetch。

当iOS决定授予您的应用一些周期时,您可以在以下位置运行简短任务:

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
    [self serverCall];  // BUT! read on
}

但是你需要重构你的serverCall来告诉调用者什么时候完成。否则,您将不知道何时调用completionHandler:

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
    [self newServerCallWithCompletion:^(BOOL gotNewData) {
        UIBackgroundFetchResult result = (gotNewData)? UIBackgroundFetchResultNewData : UIBackgroundFetchResultNoData;
        completionHandler(result);
    }];
}

有关UIBackgroundFetchResult的更多选项,请参阅文档。

有了这个,iOS将设置请求的速度,因此你将无法使它们更频繁,而不是你的应用程序有机会。通过持续上次请求的时间,您可以减少请求的请求。只需检查自上次请求以来的间隔是<=到某个所需的最大频率。如果是,只需使用“无数据”立即调用completionHandler。