NSTimer 的 isValid 总是 returns YES

NSTimer's isValid always returns YES

所以我有一个重复的计时器。每次触发时,执行的方法都会根据我的应用程序的某些内部逻辑决定是否重新安排它。

此方法可从应用程序的其他部分使用,因此我在该方法中做的第一件事是检查计时器是否仍然有效(以了解发起者是计时器还是其他实体) 所以如果它不是由计时器启动的,我想让它无效:

if (self.pollingTimer.isValid) {
    [self.pollingTimer invalidate];
    self.pollingTimer = nil;
}

我注意到,如果由于计时器被触发而调用该方法 - 我总是从 isValid 属性 收到一个真值,即使在查看 NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval)seconds target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats 方法下的文档:

repeats
If YES, the timer will repeatedly reschedule itself until invalidated. If NO, the timer will be invalidated after it fires.

Discussion
After seconds seconds have elapsed, the timer fires, sending the message aSelector to target.

我很难理解计时器何时会自动失效,这让我想到了我的问题:

  1. 知道为什么我总是从 isValid 得到 YES 吗?
  2. 计时器触发的确切定义是什么?它只是按照文档中的说明将消息 aSelector 发送到 target 吗?或者它正在完成方法的执行? (这可能解释了我正在经历的事情)

提前致谢。

计时器不是实时机制;它仅在添加了定时器的 运行 循环模式之一为 运行ning 并且能够检查定时器的触发时间是否已过时触发。因此,计时器不会立即使自己失效,而是在 运行 循环结束时。

作为简单测试,可以看到:

- (void)viewDidLoad {
  [super viewDidLoad];
  _timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(timerFired) userInfo:nil repeats:NO];

  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    if (self.timer.isValid){
        NSLog(@"--> TIMER VALID");
    } else {
        NSLog(@"TIMER INVALID!");
    }
  });
}

- (void) timerFired {
  if (self.timer.isValid){
     NSLog(@"--> TIMER VALID");
  } else {
     NSLog(@"TIMER INVALID!");
  }
}

这将从 timerFired 方法中记录 --> TIMER VALID,当调用 dispatch_after 中的块时,您将看到 TIMER INVALID!。因此,当您使用 repeats:NO 安排计时器时,它 保证 不会重新安排自己,但它不会立即失效。

所以,回答你的问题:

repeats

If YES, the timer will repeatedly reschedule itself until invalidated. If NO, the timer will be invalidated after it fires (but not immediately)

我做了这样的测试:

self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(xx) userInfo:nil repeats:NO];

- (void)xx
{
if ([self.timer isValid]) {
    NSLog(@"isvalid");
}
dispatch_async(dispatch_get_main_queue(), ^{
    if ([self.timer isValid]) {
        NSLog(@"isvalid");
    }else{
        NSLog(@"isInvalid");
    }
});
static int i = 0;
NSLog(@"%d",i++);
}

结果是:

isvalid 0 isInvalid

因此,我猜当计时器被触发时,函数是这样执行的:

void __NSFireTimer(){
id yourObj;
[yourObj performSelector:@selector(yourSelector)];
timer.isvalid = NO;
}

你相信的是:

void __NSFireTimer(){
id yourObj;
timer.isvalid = NO;
[yourObj performSelector:@selector(yourSelector)];
}

所以,只要接受 it.You 就可以把你的检查有效代码放在 dispatch_asyn() 中,就像测试代码一样。

这就是我使用计时器的方式。首先在顶部将其初始化为

@property (strong, nonatomic) NSTimer *refreshTimer;

然后这两个方法,创建和使定时器失效。 "Its very important to invalidate the current timer if you want to create another timer with same name" 否则他们将是两个计时器。

- (void)startTimer {

    if (_refreshTimer) {
        [self invalidateTimer];
    }
    _refreshTimer = [NSTimer scheduledTimerWithTimeInterval:15.0 
                                                     target:self 
                                                   selector:@selector(determineIfPartOfgroup) 
                                                   userInfo:nil 
                                                    repeats:YES];
}

- (void)invalidateTimer {

    if (_refreshTimer) {
        [_refreshTimer invalidate];
        _refreshTimer = nil;
    }
}

希望对您有所帮助。