即使计时器在视觉上停止,NSTimer也会继续计数

时间:2013-12-11 20:40:58

标签: ios nsdate nstimer

我正在创建一个格式为HH:mm的计时器,但我现在的问题是暂停计时器并恢复它。现在,当您暂停计时器时,它会继续在后台计数,但可见部分已停止。一旦你点击了继续按钮,计时器就会更新到它停止的位置,等待它暂停了多长时间,可以是任何超出它应该的数字。

例如,如果计时器计数到5,则暂停计时器,现在位于5,一旦你点击恢复,计时器可以从15开始,因为你暂停了10秒。下面是我的代码,我从几个地方合并来实现这个目的:

- (void) createTimerPage
{
    _dateFormat = [NSDate date];

    // Add pause button
    UIImage *pause = [UIImage imageNamed:@"pause.png"];
    _pauseBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    _pauseBtn.frame = CGRectMake(151, 17, 32, 32);
    [_pauseBtn addTarget:self action:@selector(pauseTimer) forControlEvents:UIControlEventTouchUpInside];
    [_pauseBtn setBackgroundImage:pause forState:UIControlStateNormal];
}

- (void) startTimer
{
    // Start timer
    NSInteger secondsSinceStart = (NSInteger) [[NSDate date] timeIntervalSinceDate:_dateFormat];
    NSInteger seconds = secondsSinceStart % 60;
    NSInteger minutes = (secondsSinceStart / 60) % 60;
    NSString *result = nil;
    result = [NSString stringWithFormat:@"%02d:%02d", minutes, seconds];
    _timerText.text = result;
    [_timerBtns addSubview:_pauseBtn];
}

- (void) startPressed
{
   [_time invalidate];
   _time = [NSTimer scheduledTimerWithTimeInterval:1.0
                                        target:self
                                        selector:@selector(startTimer)
                                       userInfo:nil
                                        repeats:YES];
}

- (void) pauseTimer
{
    if (_time) {
        // pause timer
        [_time invalidate];
        [_timerBtns addSubview:_playBtn];
    }
}

2 个答案:

答案 0 :(得分:1)

我怀疑问题在于您将“开始时间”存储在名为“_dateFormat”的变量中。该变量仅在调用createTimerPage时设置,因此,当您稍后尝试在startTimer中确定secondsSinceStart时,它仍在计算自调用createTimerPage以来的时间。

老实说,对于你想要做的事情,我根本不担心开始时间。相反,我只会使用计数器调用计时器方法的次数。我还会重命名你的一些方法,以使它更清楚实际发生的事情。例如,您的“startTimer”方法实际上并没有启动计时器。这是你的一秒计时器启动时被调用的内容。

最后,另一个问题是您不断添加子视图,但至少在发布的代码中,从不删除它们。您可以(应该)在每次添加新子视图时删除未使用的子视图。不过,老实说,最好将两个视图作为视图层次结构的一部分,并使用隐藏属性仅显示其中一个。

这样的事情会做你想做的事情:

NSUInteger _timerSeconds;
NSTimer * _timer;

- (void) createTimerPage
{
    // Add pause button
    UIImage *pause = [UIImage imageNamed:@"pause.png"];
    _pauseBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    _pauseBtn.frame = CGRectMake(151, 17, 32, 32);
    [_pauseBtn addTarget:self action:@selector(pausePressed) forControlEvents:UIControlEventTouchUpInside];
    [_pauseBtn setBackgroundImage:pause forState:UIControlStateNormal];
    [_timerBtns addSubview:_pauseBtn];
}

- (void) timerFired
{
    _timerSeconds++;
    NSInteger seconds = _timerSeconds % 60;
    NSInteger minutes = (_timerSeconds / 60) % 60;
    NSString * result = [NSString stringWithFormat:@"%02d:%02d", minutes, seconds];
    _timerText.text = result;
}

- (void) startPressed
{
    // start timer
    _timer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                             target:self
                                           selector:@selector(timerFired)
                                           userInfo:nil
                                            repeats:YES];

    _playBtn.hidden = YES;
    _pauseBtn.hidden = NO;
}

- (void) pausePressed
{
    if (_timer) {
        // pause timer
        [_timer invalidate];
        _playBtn.hidden = NO;
        _pauseBtn.hidden = YES;
    }
}

答案 1 :(得分:0)

我实际上能够通过对此事的更多研究来解决这个问题。我找到了一个很好的例子,帮助我提出以下建议:

- (IBAction)startRepeatingTimer:(id)sender
{
    // Show feed text while timer is going
    _feeding = [[UILabel alloc] initWithFrame:CGRectMake(92, 25, 100, 50)];
    _feeding.text = @"FEEDING";
    _feeding.textColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
    if (_feeding) {
        _feeding.hidden = NO;
    }
    [_timerArea addSubview:_feeding];

    // Cancel preexisting timer
    [_repeatingTimer invalidate];

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                                  target:self 
                                                selector:@selector(timerTicked:)
                                                userInfo:nil repeats:YES];
    _repeatingTimer = timer;
    if (_playBtn.hidden == NO) {
        _playBtn.hidden = YES;
        _pauseBtn.hidden = NO;
    }

    if (_bWindow.frame.origin.y == 0) {
        [UIView animateWithDuration:0.3
                     animations:^ {
                         _bWindow.frame = CGRectMake(0, 0, self.view.frame.size.width, 203);
                         _bWindow.frame = CGRectMake(0, -130, self.view.frame.size.width, 203);
                     }];
    }

    [_timerBtns addSubview:_pauseBtn];
}

- (void) timerTicked:(NSTimer *)timer
{
    _currentTimeInSeconds++;
    _timerText.text = [self targetMethod:_currentTimeInSeconds];
}

- (IBAction)resetTimer:(id)sender
{
    _feeding.hidden = YES;
    if (_repeatingTimer) {
        [_repeatingTimer invalidate];
    }
    if (_playBtn.hidden == YES) {
        _playBtn.hidden = NO;
        _pauseBtn.hidden = YES;
    }
    _currentTimeInSeconds = 0;
    _timerText.text = [self targetMethod:_currentTimeInSeconds];
    if (_bothBtn.hidden == YES) {
        _bothBtn.hidden = NO;
        _switchBView.hidden = YES;
    }
    if (_rightBtn.hidden == YES) {
        _rightBtn.hidden = NO;
        _switchRView.hidden = YES;
    }
    if (_leftBtn.hidden == YES) {
        _leftBtn.hidden = NO;
        _switchLView.hidden = YES;
    }
}

- (IBAction)pauseRepeatingTimer:(id)sender
{
    [_repeatingTimer invalidate];
    if (_playBtn.hidden == YES) {
        _playBtn.hidden = NO;
        _pauseBtn.hidden = YES;
    }
}

- (NSString *) targetMethod:(int)totalSeconds
{
    //NSInteger secondsSinceStart = (NSInteger) [[NSDate date] timeIntervalSinceDate:_dateFormat];
    int seconds = totalSeconds % 60;
    int minutes = (totalSeconds / 60) % 60;
    return [NSString stringWithFormat:@"%02d:%02d", minutes, seconds];
}