【问题标题】:NSTimer Press "Start" Again then Cannot "Stop"NSTimer 再次按“开始”然后无法“停止”
【发布时间】:2016-06-01 16:08:56
【问题描述】:

一个奇怪的情况:

如果我一次又一次地启动我的计时器而不先停止它,它的计数会越来越快。我猜是因为它现在启动了多个计时器?

然而,当我终于想阻止它时,它无法阻止……永远继续下去。

(也许出于设计考虑,我应该禁止用户再次按开始,但我想知道这背后的真正原因是什么以及为什么无法停止计时器。)

- (IBAction)Start:(id)sender {
    countInt = 0;
    self.Time.text = [NSString stringWithFormat:@"%i", countInt];
    timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(countTimer) userInfo:nil repeats:YES];
}

- (IBAction)Stop:(id)sender {
    [timer invalidate];
}

- (void) countTimer {
    countInt += 1;
    self.Time.text = [NSString stringWithFormat:@"%i", countInt];
}
@end

【问题讨论】:

  • 显示你的代码,大概你没有失效,你也杀死了你对计时器的引用......
  • 贴代码,不是图片! - 编辑您的问题。
  • @Wain 感谢您的快速回复!我添加了一个屏幕截图......不确定它是否是正确的附加方式。我确实使计时器无效。
  • @vadian 谢谢!我只是想出了如何发布代码...

标签: ios objective-c nstimer


【解决方案1】:

简单的解决方案是在start方法的开头调用stop

请注意,在stop 中您还应该设置timer = nil;

【讨论】:

  • 酷。为什么要将计时器设置为“nil”?停止对象时是否总是需要将对象设置为零?
  • 您希望timer 在使其失效后设置为nil,否则您最终可能会再次尝试引用失效的计时器指针。通过将其设置为nil,您将不会出现此问题。
【解决方案2】:

假设有一个属性timer

@property NSTimer *timer;

分别只启动和停止一次计时器最可靠的方法是创建两个方法。

- (void)startTimer
{
    if (self.timer == nil) {
        self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 
                                                      target:self 
                                                    selector:@selector(countTimer) 
                                                    userInfo:nil 
                                                     repeats:YES];
    }
}

- (void)stopTimer
{
    if (self.timer != nil) {
        [self.timer invalidate];
        self.timer = nil;
    }
}

两种方法都执行检查,因此计时器在运行时无法重新启动,反之亦然。

现在只需调用start/stop IBActions 中的方法(名称应以小写字母开头)。

- (IBAction)Start:(id)sender {
    countInt = 0;
    self.Time.text = [NSString stringWithFormat:@"%i", countInt];
    [self startTimer];
}

- (IBAction)Stop:(id)sender {
   [self stopTimer];
}

好处是在计时器已经运行时按Start 无效。

【讨论】:

  • 只有一点点:不需要签入-stopTimer:,因为如果是nil,则不会执行任何操作。
  • 其实没错,但是发送两条消息到一个nil指针(一条消息和一个冗余分配)比发送一个更有效吗? > 检查?
  • 哇,我真的不认为操作方法会出现性能问题,因为有两条消息为零,一条消息不为零。 (但是,他们将消息的行为优化为 nil。)这只是为了代码的简洁性。
  • 这当然不是一个问题,但我个人一直在寻找最有效的代码,而不是最短的。
  • 我个人正在寻找最好的可读性,通常是最短的。 (不,当短小是典型的“C hacks”的结果时不是。)然而,这是一个小评论。不值得无休止的讨论。 (我更喜欢韦恩的回答。)
【解决方案3】:

当您多次点击“开始”时,您将创建多个计时器。因此,您将获得多个计时器触发并执行计时器回调。在此计时器回调中,您递增计数器。由于现在有很多计时器,它们都在增加你的计数器,因此解释了你的计数器快速增加。

您可以允许用户点击 Start 两次,只要您可以定义当您在计时器已经运行时点击 Start 时会发生什么。但在创建新计时器之前,您绝对需要invalidate 旧计时器。

- (IBAction)Start:(id)sender {
    ...
    // Stop previous timer before creating a new timer.
    if (timer != nil) {
        [timer invalidate]
    }
    ...
}

【讨论】:

  • 谢谢!在开始时“呼叫停止”是使旧计时器无效的最佳方法吗?
  • 这是一种方式。您也可以手动调用 [timer invalidate]。取决于 Stop 方法的实际实现。
猜你喜欢
  • 2020-02-21
  • 1970-01-01
  • 2019-01-18
  • 2023-03-09
  • 2018-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多