iOS中App进入后台,定时器继续执行

需求:点击发送验证码并切换到后台,验证码倒计时不停止

一、直接法

Apple只允许三种情况下App在后台一直执行,音频视频、定位、未知(还有一种没查到),如果是直播、视频播放、地图类的应用可以这样做,但是有些小需求则无需这样。

二、障眼法(不推荐)
{
  int _countdownTimer;      //倒计时
}

@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, assign) NSTimeInterval timestamp;


- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self observeApplicationActionNotification];
}

- (void)getCodeBtnClick
{
    xxxxxxxxxxxxx
    
    if (获取验证码成功)  {
            getVerificationCodeBtn.enabled = NO;
            self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerFireMethod:) userInfo:nil repeats:YES];
        }
}

- (void)timerFireMethod:(NSTimer *)timer
{
    NSString *remindWords = [NSString stringWithFormat:@"重新发送(%ds)", _countdownTimer--];
    [_activatorView.getVerificationCodeBtn setTitle:remindWords forState:UIControlStateNormal];
    [_activatorView.getVerificationCodeBtn setTitle:remindWords forState:UIControlStateDisabled];

    if (_countdownTimer <= 0) {
        [_activatorView.getVerificationCodeBtn setTitleColor:[TKUIHelper colorWithHexString:@"4359aa"] forState:UIControlStateNormal];
        [timer invalidate];
        timer = nil;
        _countdownTimer = kCountdown;
        [_activatorView.getVerificationCodeBtn setTitle:@"发送验证码" forState:UIControlStateNormal];
        _activatorView.getVerificationCodeBtn.enabled = YES;
    }
}


- (void)dealloc {
    
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)observeApplicationActionNotification {
    
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground) name: UIApplicationDidEnterBackgroundNotification object:nil];
}

- (void)applicationDidEnterBackground {
    
    _timestamp = [NSDate date].timeIntervalSince1970;
    _timer.fireDate = [NSDate distantFuture];
}

- (void)applicationDidBecomeActive {
        
    NSTimeInterval timeInterval = [NSDate date].timeIntervalSince1970-_timestamp;
    _timestamp = 0;
    
    NSTimeInterval ret = _countdownTimer-timeInterval;
    if (ret>0) {
        _countdownTimer = ret;
        _timer.fireDate = [NSDate date];
    } else {
        _countdownTimer = 0;
        _timer.fireDate = [NSDate date];
        [self timerFireMethod:self.timer];
    }
}

原理:监听进入后台、进入后台的消息,在进入后台时存时间戳,停掉定时器(系统会强制停止定时器);在进入前台时计算时间差。如果剩余时间大于时间差,则减去时间差,否则赋值剩余时间为0。这里为了体验更好,添加了停止和启动定时器的操作。

通过上面的代码,可以在App进入前、后台时做一些计算和定时器操作,完成定时器在后台执行的效果。

参考:iOS程序进入后台后仍运行定时器NSTimer问题

三、障眼法2(推荐)

这里简单说一下思路:借助于时间戳。
1、记录验证码发送成功时的时间戳timestamp。
2、在每次页面将要显示时获取的时间戳timestamp2,把这两个时间戳相减。大于60秒,就不显示倒计时,显示可继续点击发送验证码;小于60秒就显示这两个时间差,按钮不可点击。

这样不用监听通知等复杂的操作了也能实现该需求。

你可能感兴趣的:(iOS中App进入后台,定时器继续执行)