我们都知道NStimer 在iPhone里面后台的可以运行时间是3分钟。即使挂在前台,只要手机开始锁屏了。NSTimer会立即停止运行。即使如下面这样
- (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.
UIApplication* app = [UIApplication sharedApplication];
__block UIBackgroundTaskIdentifier bgTask;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
{
bgTask = UIBackgroundTaskInvalid;
}
});
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
if (bgTask != UIBackgroundTaskInvalid)
{
bgTask = UIBackgroundTaskInvalid;
}
});
});
}
搭配
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance]
setCategory: AVAudioSessionCategoryPlayback
error: &setCategoryErr];
[[AVAudioSession sharedInstance]
setActive: YES
error: &activationErr];
也不能完全实现效果 进入后台超过一定时间还是会被停止。而且还有审核的风险
在我的APP里面我使用到了定位。一直开启了定位但是过了一定的时间定时器还是会被停止。虽然一直在定位
经过调试我发现程序锁屏和解锁的时候仍然分别会发送
UIApplicationDidEnterBackgroundNotification和 UIApplicationWillEnterForegroundNotification这2个通知。因为程序进入后台啊UI上的操作一直都是停止的。所以我们可以在程序再次激活的时候去刷新界面。这样我们只要保留下进入后台的时间保留下当前的时间,程序进入前台的时候计算他们的时间差值再加上之前定时器已经运行的时间。计算时间差值的方法如下
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
unsigned int unitFlags = NSSecondCalendarUnit;//年、月、日、时、分、秒、周等等都可以
NSDateComponents *comps = [gregorian components:unitFlags fromDate:self.EnterBackGroundTime toDate:[NSDate date] options:0];
NSLog(@"comps%d",[comps second]);
这样我们就可以得到所有的时间。数据类的获取一般都不交给定时器。通过定位循环获取。这样计算平均速度什么的就不会有什么误差。
还有我们可以新建一个方法通过sleep实现定时器的效果,这样的实现在屏幕锁定或者进入后台的时候仍然有效。不过一定要放到子线程中否则会堵塞界面操作。