使用 NSTimer 的秒表错误地在显示中包含暂停时间 [英] Stopwatch using NSTimer incorrectly includes paused time in display

查看:20
本文介绍了使用 NSTimer 的秒表错误地在显示中包含暂停时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的 iPhone 秒表代码.它按预期工作,并在单击按钮时停止和恢复.

This is my code for an iPhone stopwatch. It works as expected and stops and resumes when the buttons are clicked.

然而,当我点击停止"时,计时器不会停止在后台运行,当我点击开始"恢复它时,它会更新时间并跳到当前位置而不是从那里恢复停止的时间.

When I hit "Stop", however, the timer won't stop running in the background, and when I hit "Start" to resume it, it will update the time and skip to where it is currently instead of resuming from the stopped time.

如何停止 NSTimer?是什么导致了这种情况?

How can I stop the NSTimer? What is causing this to occur?

@implementation FirstViewController;
@synthesize stopWatchLabel;

NSDate *startDate;
NSTimer *stopWatchTimer;
int touchCount;


-(void)showActivity {

    NSDate *currentDate = [NSDate date];
    NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate];
    NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"mm:ss.SS"];
    [dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
    NSString *timeString=[dateFormatter stringFromDate:timerDate];
    stopWatchLabel.text = timeString;
    [dateFormatter release];
}

- (IBAction)onStartPressed:(id)sender {

    stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1/10 target:self selector:@selector(showActivity) userInfo:nil repeats:YES];

    touchCount += 1;
    if (touchCount > 1)
    {
        [stopWatchTimer fire];
    }
    else 
    {
        startDate = [[NSDate date]retain];
        [stopWatchTimer fire];

    }
}

- (IBAction)onStopPressed:(id)sender {
    [stopWatchTimer invalidate];
    stopWatchTimer = nil;
    [self showActivity];
}

- (IBAction)reset:(id)sender; {
    touchCount = 0;
    stopWatchLabel.text = @"00:00.00";
}

推荐答案

你对当前显示的计算总是使用定时器原来的开始时间,所以暂停后的显示包含了定时器暂停的时间间隔.

Your calculation of the current display always uses the original start time of the timer, so the display after pausing includes the interval that the timer was paused.

最简单的方法是在计时器暂停时存储另一个 NSTimeInterval,例如 secondsAlreadyRun,并将其添加到您在恢复时计算的时间间隔.您需要在计时器开始计数时更新计时器的startDate .在 reset: 中,您还需要清除 secondsAlreadyRun 间隔.

The easiest thing to do would be to store another NSTimeInterval, say secondsAlreadyRun, when the timer is paused, and add that to the time interval you calculate when you resume. You'll want to update the timer's startDate every time the timer starts counting. In reset:, you would also clear out that secondsAlreadyRun interval.

-(void)showActivity:(NSTimer *)tim {

    NSDate *currentDate = [NSDate date];
    NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate];
    // Add the saved interval
    timeInterval += secondsAlreadyRun;
    NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"mm:ss.SS"];
    [dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
    NSString *timeString=[dateFormatter stringFromDate:timerDate];
    stopWatchLabel.text = timeString;
    [dateFormatter release];
}

- (IBAction)onStartPressed:(id)sender {

    stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1/10 
                                                      target:self 
                                                    selector:@selector(showActivity:) 
                                                    userInfo:nil 
                                                     repeats:YES];
    // Save the new start date every time
    startDate = [[NSDate alloc] init]; // equivalent to [[NSDate date] retain];
    [stopWatchTimer fire];
}

- (IBAction)onStopPressed:(id)sender {
    // _Increment_ secondsAlreadyRun to allow for multiple pauses and restarts
    secondsAlreadyRun += [[NSDate date] timeIntervalSinceDate:startDate];
    [stopWatchTimer invalidate];
    stopWatchTimer = nil;
    [startDate release];
    [self showActivity];
}

- (IBAction)reset:(id)sender; {
    secondsAlreadyRun = 0;
    stopWatchLabel.text = @"00:00.00";
}

不要忘记在适当的地方发布startDate!还要记住,记录在案的 NSTimer 接口是用于你给它接受一个参数的方法,这将是计时器本身.没有它似乎也能工作,但为什么要诱惑命运?

Don't forget to release that startDate somewhere appropriate! Also keep in mind that the documented NSTimer interface is for the method you give it to accept one argument, which will be the timer itself. It seems to work without that, but why tempt fate?

最后,由于您经常使用 NSDateFormatter,您可能需要考虑将其设为 ivar 或将其放入 showActivity 的 static 存储中:,像这样:

Finally, since you're using that NSDateFormatter so much, you might want to consider making it an ivar or put it in static storage in showActivity:, like so:

static NSDateFormatter * dateFormatter = nil;
if( !dateFormatter ){
    dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"mm:ss.SS"];
    [dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
}

这篇关于使用 NSTimer 的秒表错误地在显示中包含暂停时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆