NSTimer捶打 - 我需要处理吗?

时间:2012-12-01 02:48:47

标签: ios nstimer

这个问题可能已经存在,但我找不到它。我的问题基本上就是这个。如果我有一个重复的NSTimer执行一些比定时器间隔更长的东西,会不会有一些颠簸会让应用程序崩溃?或者,新的时间事件是否在正在执行的任务完成之前才开始?

4 个答案:

答案 0 :(得分:2)

由于NSTimer在运行循环上运行,因此它创建了,我认为它不能重新输入它调用的方法。这个document on the run loops证实了这一点(参见“计时器来源”部分:

  

“同样,如果计时器在运行循环处于中间时触发   执行处理程序例程,计时器等到下一次   通过运行循环来调用其处理程序例程“

答案 1 :(得分:1)

您始终只需安排一次仅出现一次的定时器,然后在该功能完成时重新安排它。

- (void)myFunction {
    ......stuff that your method does
    [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(myFunction) userInfo:nil repeats:NO];
}

答案 2 :(得分:0)

重复计时器总是根据计划的点火时间来计划自己,而不是实际点火时间。例如,如果计划在特定时间和之后每5秒计时一次计时器,则计划的点火时间将始终落在原始的5秒时间间隔上,即使实际点火时间延迟。如果射击时间延迟到目前为止它通过一个或多个预定的射击时间,则计时器仅在该时间段内被触发一次;然后,计时器在射击后重新安排,用于将来的下一个预定射击时间。

https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/Reference/NSTimer.html

答案 3 :(得分:0)

只要你避免开始一些异步工作,你就没事了。如果异步调度任务通常需要的时间超过计时器调用之间的间隔,那么该队列可以得到备份。如果正在制作动画,即使动画可能无法完成,计时器也会启动。


让我举两个例子。对于这两个例子,让我们假设我们创建一个每秒触发一次的计时器:

self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                              target:self
                                            selector:@selector(handleTimer:)
                                            userInfo:@"tick"
                                             repeats:YES];

第一个例子:我们假设我们有一些串行队列:

self.queue = [[NSOperationQueue alloc] init];
self.queue.maxConcurrentOperationCount = 1;

此外,我们假设我们有一个NSTimer处理程序,它可以执行以下操作:

- (void)handleTimer:(NSTimer *)timer
{
    NSLog(@"%s %@", __FUNCTION__, timer.userInfo);

    [self.queue addOperationWithBlock:^{

        NSLog(@"%s starting some slow process; has %d operations queued", __FUNCTION__, self.queue.operationCount);

        // to simulate a slow process, let's just sleep for 10 seconds

        sleep(10);

        NSLog(@"%s done", __FUNCTION__);
    }];
}

因为计时器每秒都会触发,并且因为计时器处理程序几乎立即返回(因为它正在进行的所有操作都在排队后台操作),所以当第一个排队操作(需要10秒)完成并且第二个排队操作开始时,已经有10个操作位于该后台队列中。当第二次后台操作完成时,当第三次操作开始时,有19个操作排队。它只会变得更糟,因为NSTimer处理程序将继续被调用,比较慢的后台操作被清除出队列更快。显然,如果处理程序在当前队列中同步执行了所有操作,那么一切都很好,并且没有积压,NSTimer没有“捶打”。

第二个例子:此问题的另一个例子是动画。让我们假设计时器处理程序方法正在执行类似下面的操作:启动一个移动UIImageView的10秒动画:

- (void)handleTimer:(NSTimer *)timer
{
    NSLog(@"%s %@", __FUNCTION__, timer.userInfo);

    [UIView animateWithDuration:10.0
                     animations:^{
                         self.imageView.frame = [self determineNewFrame];
                     }
                     completion:nil];
}

这不起作用(或者更确切地说,即使前一个动画没有完成,你也会看到定时器调用handleTimer的后续调用)。如果你要这样做,你必须跟踪动画是否完成。你必须做类似的事情:

- (void)handleTimer:(NSTimer *)timer
{
    NSLog(@"%s %@", __FUNCTION__, timer.userInfo);

    if (!self.animating)
    {
        NSLog(@"%s initiating another animation", __FUNCTION__);

        [UIView animateWithDuration:10.0
                         animations:^{
                             self.animating = YES;
                             self.imageView.frame = [self determineNewFrame];
                         }
                         completion:^(BOOL finished){
                             self.animating = NO;
                         }];
    }
}

你要么必须做一些状态标志(比如我的布尔animation标志),以防止在第一个完成之前有额外的动画,或者只是不使用定期计时器,只需启动{{1中的另一个计时器completion动画类方法的块。