0

我正在设置一个计时器,以 13 分钟的间隔触发。但是计时器似乎以不规则的间隔被触发。这是一个间歇性问题。一些用户报告了这个问题,我无法重现相同的问题。

- (void)resetIdleTimer
{
    if (_idleTimer)
    {
        [_idleTimer invalidate];
        [_idleTimer release];
        _idleTimer = nil;
    }

    _idleTimer = [[NSTimer scheduledTimerWithTimeInterval:13*60.0
                                                   target:self
                                                 selector:@selector(idleTimerExceeded)
                                                 userInfo:nil
                                                  repeats:NO] retain];
}

- (void)idleTimerExceeded
{
        // do some processing
    [_idleTimer release];
    _idleTimer = nil;
}

定时器将根据某些条件被重置(resetIdleTimer),但无论如何都会将定时器重置为 13 分钟。

当我查看代码时,我只能看到没有将计时器参数传递给选择器的问题。我不确定这是否是这个问题的原因?有没有人遇到过这种怪事?(我将如何更新代码以将计时器作为参数)。一位用户报告说它只是在 4 分钟后发生。

4

3 回答 3

1

让我们确认一件事,不将计时器参数传递给选择器不会导致任何问题。

这是工作正常的更新代码

@property(nonatomic,strong)NSTimer *myTimer;

或者

 @property(nonatomic,retain)NSTimer *myTimer;

方法

- (void)resetIdleTimer
{

  if ([self.myTimer isValid]) 
        [self.myTimer invalidate];

   self.myTimer = [NSTimer scheduledTimerWithTimeInterval:13*60.0
                                 target:self
                               selector:@selector(idleTimerExceeded)
                               userInfo:nil
                                repeats:NO];
} 
- (void)idleTimerExceeded
{
  NSLog(@"tiggered");
}
于 2013-03-15T07:55:43.710 回答
0

我在你的代码中没有发现任何错误,唯一的想法是用户进入你的类创建一个实例,我们称之为实例“A”,然后启动计时器,然后在 13 分钟前退出你的类,然后再次输入有了一个新的实例“B”,一个新的计时器开始......

此时用户希望您的计时器方法在 13 分钟后触发......但“A”的计时器仍在等待中(因为您关闭课程的方式可能存在错误)并执行......

您可以尝试添加一些日志并尝试按照我说的做,并检查所有日志(特别是如果您输入了 dealloc,并且 idleTimerExceeded 打印实例中的日志等于 resetIdleTimer 中打印的最后一个实例):

    -(void)resetIdleTimer  {
            if (_idleTimer)
            {
                [_idleTimer invalidate];
                [_idleTimer release];
                _idleTimer = nil;
            }

            NSLog(@"...resetIdleTimer: instance: %p", self);
            _idleTimer = [[NSTimer scheduledTimerWithTimeInterval:13*60.0
                                                           target:self
                                                         selector:@selector(idleTimerExceeded)
                                                         userInfo:nil
                                                          repeats:NO] retain];
             NSLog(@"...resetIdleTimer: _idleTimer: %p", _idleTimer);
       }

        - (void)idleTimerExceeded
        {
                // do some processing
            NSLog(@"...idleTimerExceeded: instance: %p", self);
            NSLog(@"...idleTimerExceeded: _idleTimer: %p", _idleTimer);

            [_idleTimer release];
            _idleTimer = nil;
        }


        -(void) dealloc 
        {
            NSLog(@"...dealloc: instance: %p", self);
            [super dealloc];

        }

只是一个想法...但是您可能忘记了计时器保留了传入target:参数的实例(您传递了“self”,因此保留了您的类实例),因此一个常见的错误是在关闭类实例时忘记关闭计时器.

正确的方法应该是:

-a 根类 (AAA) 使用计时器实例化您的类 (BBB) -BBB 启动它的计时器 -AAA 想要 dealloc/resetIdleTimer 类 BBB:在释放之前它必须停止/使 BBB.timer 无效(如果不是计时器,则保留 BBB,并且 BBB 获胜'直到计时器触发/执行其方法才被释放)

因此,如果是您的情况...添加一个可以从 AAA 类调用的方法,该方法可以停止/使计时器无效,例如:

-(void)stopTimer{
                if (_idleTimer)
                {
                    [_idleTimer invalidate];
                    [_idleTimer release];
                    _idleTimer = nil;
                }
}
于 2013-03-15T09:19:21.083 回答
0

如果您希望计时器在 13 分钟内准确触发,也许这会有所帮助:

https://stackoverflow.com/a/3519913/1226304

于 2013-03-15T10:37:34.527 回答