NSTimer后台无限计时

先介绍一下网上比较多的一种解决方案:
在AppDelegate或NSTimer定义的地方加入如下代码,实现让App进入后台NSTimer继续计时:

UIApplication*  app = [UIApplication sharedApplication];
    self.bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:self.bgTask];
        self.bgTask = UIBackgroundTaskInvalid;
    }];

经测试发现当app进入后台的确能正常计时, 这种方法有什么问题呢?

  1. 这个是苹果官方提供的一种方法,最多只能维持app在后台10分钟。超过了时间NSTimer一样会停止,起不到无限计时的作用。
  2. 经测试在iOS9上只能维持1-2分钟。

下面来看一下iOS提供的5中后台无限运行模式:

  • 播放音频-----应用程序可以在后台持续的播音或者录音。
  • 接收位置更新-----随着设备位置的变化应用程序要持续获得地理位置更新。
  • 执行有限长度的任务----在有限的时间内,无论任何情况下应用程序都可以执行任何代码。
  • 正在下载杂志-----杂志类应用特例,应用程序能够在后台下载
  • 提供voip(voice-over-ip)服务---应用程序能够在后台执行任意的代码,当然苹果会限制它的用途,你的应用必须提供voip服务。

我们要实现NSTimer无限计时就必须要借助这5种模式中的一种, 下面我们就以播放音频为例来说明。

  1. 在Info.plist中配置权限。


    图片.png
  2. 导入AVFoundation库,在AppDelegate中加入以下代码:
@property(nonatomic, strong) AVAudioPlayer *audioPlayer;
@property(nonatomic, assign) UIBackgroundTaskIdentifier bgTask;
-(void)applicationDidEnterBackground:(UIApplication *)application{
    UIApplication*  app = [UIApplication sharedApplication];
    self.bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:self.bgTask];
        self.bgTask = UIBackgroundTaskInvalid;
    }];
    [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(applyForMoreTime) userInfo:nil repeats:YES];
}
-(void)applyForMoreTime {
    if ([UIApplication sharedApplication].backgroundTimeRemaining < 30) {
        NSURL *filePathUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"1" ofType:@"wav"]];
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
        self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:filePathUrl error:nil];
        [self.audioPlayer play];
        [[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
        self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
            [[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
            self.bgTask = UIBackgroundTaskInvalid;
        }];
    }
}

经测试上述代码能保证NSTimer在后台无限计时了。

github代码下载地址: here

你可能感兴趣的:(NSTimer后台无限计时)