1. 程式人生 > >如何讓NSTimer變相的在後臺長時間執行

如何讓NSTimer變相的在後臺長時間執行

我們都知道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實現定時器的效果,這樣的實現在螢幕鎖定或者進入後臺的時候仍然有效。不過一定要放到子執行緒中否則會堵塞介面操作。