【问题标题】:After resuming timer, timer counts twice as fast恢复定时器后,定时器计数快两倍
【发布时间】:2013-03-27 09:55:36
【问题描述】:

我现在正在学习 Mac OS X 编程。我的第一个项目是写一个简单的秒表。我知道您可以使用 NSTimer,但我想如果我自己完成所有工作,我会学到更多。该应用程序运行良好。但是在恢复秒表后,它会跳过每秒的数字..

代码如下:

- (IBAction)stop:(id)sender {
    started = FALSE;
    NSLog(@"Stop pressed: %i", started);
}

- (IBAction)start:(id)sender {
    if(!started){
        started = TRUE;
        [self tock:nil];  
    }
    else {
        started = FALSE; 
    }
}

- (void) tock:(id)sender { 
     if(started == TRUE) {
         seconds++;
     };

     [self performSelector:@selector(tock:) withObject:(self) afterDelay:(1.0)];
     _anzeige.stringValue = [NSString stringWithFormat:(@"%i"), seconds];
}

【问题讨论】:

  • 当您在点击停止和再次点击开始之间等待 2 秒时,您是否看到了这种行为?看起来你至少在点击 stop 后仍然有一个 tock 排队,它将在 1 秒后触发,导致该步骤触发,然后重新开始该过程。如果您在不到一秒的时间内单击开始,您将有 2 个在队列中,它们将分别触发并分别重生。
  • 我认为你是对的。似乎它在排队...恢复后直接看到丢失的数字闪烁...几秒钟后您看到每个数字但间隔更短...我需要如何更改代码?是的,我知道你可以用不同的方式做,但我想知道这种方式的缺陷..我还在学习

标签: iphone ios objective-c cocoa-touch nstimer


【解决方案1】:

第 1 步:在 .h 文件中声明以下两个变量

NSTimer *secondTimer;
int seconds;

第 2 步:然后将 second 初始化为 0 in

- (void)viewDidLoad
{
    seconds = 0;
}

第 3 步:编写以下方法并为各自的 Start 和 Stop 方法分配 IBOutlets

- (IBAction)stop:(id)sender
{
    // Check if time is enable stop it first    
    if([secondTimer isValid])
    {
        [secondTimer invalidate];
        secondTimer = nil;
    }
}

- (IBAction)start:(id)sender
{
    // Check if time is enable stop it first
    if([secondTimer isValid])
    {
        [secondTimer invalidate];
        secondTimer = nil;
    }

    // now start a new timer
    secondTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(tock) userInfo:nil repeats:YES];
}

- (void) tock
{
    seconds++;
    NSLog(@"%d",seconds);
    // if you want to display second in UILabel uncomment following line
    //[lbl setText:[NSString stringWithFormat:@"%d",seconds]];
}

【讨论】:

    【解决方案2】:

    您需要取消performSelector:withObject:afterDelay: 通话。否则,每次您拨打tock: 时,它们都会堆积起来。

    【讨论】:

    • 根据文档,+[NSObject cancelPreviousPerformRequestsWithTarget:selector:object:]
    【解决方案3】:

    像这样尝试并使用 NSDate 变量 lObjstrt 中的开始时间和

    NSTimeInterval lTimeInterval=[lObjCurrentDateStr timeIntervalSinceDate:lObjstrt];
    NSDate *lObjTimerDatePtr =[NSDate dateWithTimeIntervalSince1970:lTimeInterval];
    NSDateFormatter *lObjDateFormatterPtr = [[NSDateFormatter alloc] init];
    [lObjDateFormatterPtr setDateFormat:@"mm:ss.SS"];
    [lObjDateFormatterPtr setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
    NSString *m_cObjSprintTimePtr=[lObjDateFormatterPtr stringFromDate:lObjTimerDatePtr];
    NSString *m_cObjSprintTimerValuePtr = [NSString stringWithFormat:@"%@ secs", self.m_cObjSprintTimePtr];
    

    有了这个,你可以得到相应的计时器,并尝试在停止后让计时器休息:

    if((NSTimer *)nil != m_cObjSprintTimerPtr) {
        [m_cObjSprintTimerPtr invalidate];
        m_cObjSprintTimerPtr = (NSTimer *)nil;
    }
    

    【讨论】:

      【解决方案4】:

      首先,您通常只需在单独的线程中启动此类循环并使用标志控制它。 其次,如果你想让你的塞子准确,你必须在启动计时器时保存一个时间戳,并且每次你的计时器循环显示开始时间戳和当前时间戳之间的差异。例子: [[NSDate 日期] timeIntervalSinceDate:startDate];

      【讨论】:

      • 我到底得到了什么-1?
      猜你喜欢
      • 2014-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多