NSTimer的isValid始终返回YES

时间:2015-06-03 08:21:07

标签: ios nstimer

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

这个方法可以从应用程序的其他部分获得,所以我在该方法中做的第一件事是检查计时器是否仍然有效(以确定启动器是计时器还是不同的实体)所以万一它不是由计时器启动我想让它失效:

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文档时也是如此。 Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source =" 'Change the following to your access database location dataFile = "C:\Users\DELL\Downloads\WindowsApplication1\WindowsApplication1\Database1.accdb" connString = provider & dataFile myConnection.ConnectionString = connString myConnection.Open() Dim str As String str = "insert into tblODR ([ID], [Office], [Elements], [Objectives], [Initiatves]) values (?, ?, ?, ?, ?)" Dim cmd As OleDbCommand = New OleDbCommand(str, myConnection) cmd.Parameters.Add(New OleDbParameter("ID", CType(IDTextBox.Text, String))) cmd.Parameters.Add(New OleDbParameter("Office", CType(OfficeTextBox.Text, String))) cmd.Parameters.Add(New OleDbParameter("Elements", CType(ElementsTextBox.Text, String))) cmd.Parameters.Add(New OleDbParameter("Objectives", CType(ObjectivesTextBox.Text, String))) cmd.Parameters.Add(New OleDbParameter("Initiatves", CType(InitiatvesTextBox.Text, String))) Try cmd.ExecuteNonQuery() cmd.Dispose() myConnection.Close() Me.Validate() Me.TblODRBindingSource.EndEdit() Me.TblODRTableAdapter.Update(Me.Database1DataSet.tblODR) Catch ex As Exception MsgBox(ex.Message) End Try End Sub 方法:

  

重复
  如果是,则计时器将反复重新安排自己,直到无效。 如果为“否”,计时器将在激活后失效。

     

讨论
  经过几秒钟后,计时器触发,   将消息aSelector发送到目标。

我很难理解计时器何时自动失效,这引起了我的疑问:

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

3 个答案:

答案 0 :(得分:3)

计时器不是实时机制;只有当添加了计时器的其中一个运行循环模式正在运行并且能够检查计时器的触发时间是否已经过去时,它才会触发。因此,计时器不会立即使自身无效,而是在运行循环结束时。

作为一个简单的测试,您可以看到:

- (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!");
  }
}

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

所以,回答你的问题:

  

重复

     

如果是,则计时器将反复重新安排,直到   无效。如果为否,计时器将在(但不立即)

后触发无效

答案 1 :(得分:1)

我做了这样的测试:

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)];
}

所以,接受它。您可以将检查有效代码放在dispatch_asyn()中,就像测试代码一样。

答案 2 :(得分:0)

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

@property (strong, nonatomic) NSTimer *refreshTimer;
然后这两种方法,创建和使计时器无效。 "如果要创建另一个具有相同名称的计时器,则使当前计时器无效非常重要"否则他们将是两个计时器。

- (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;
    }
}

我希望这会对你有所帮助。