我正在使用一个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];
}
答案 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。