使用NSTimer的秒表不正确地包括显示中的暂停时间 [英] Stopwatch using NSTimer incorrectly includes paused time in display

查看:106
本文介绍了使用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天全站免登陆