NSTimer missing fire date when clock is manually set forward

后端 未结 1 1129
野趣味
野趣味 2021-01-04 20:58

I am setting up a timer to run a specific function in the future like this:

pingTimer = [[NSTimer alloc] initWithFireDate:pingAtDate
                                 


        
相关标签:
1条回答
  • 2021-01-04 21:32

    There were some good comments left, but no complete answers. I am going to pull all the pertinent details together here.

    An NSTimer is not a clock-time mechanism. When you set a "FireDate" you cannot be sure that the timer will actually fire at that date. You are actually telling the timer to run for specific amount of time before firing. That amount of time is the difference between when you add the timer to the run loop, and the date that you scheduled the timer to fire at.

    If your system goes to sleep (or your application is suspended), your timer is no longer ticking down. It will resume ticking down when your system wakes up (or your application becomes active), but this means that your timer will now NOT execute at the original "FireDate". Rather it will execute at the "FireDate" + (amount of time your computer was asleep).

    Similarly if a user changes the system time, this does not affect the timer in any way. If the timer was scheduled to fire at a date 8 hours in the future, it will continue ticking down 8 hours worth of time before it fires.

    In the case where you want a timer to fire at a specific clock time in the distant future, you will need to make sure your application is notified of the following events:

    1. Wake from sleep
    2. System time change

    When any of these events occur you will need to invalidate and adjust any existing timers.

    /* If the clock time changed or we woke from sleep whe have to reset these long term timers */
    - (void) resetTimers: (NSNotification*) notification
    {
        //Invalidate and Reset long term NSTimers
    }
    

    You can observe the following notifications to be notified when those events are going to happen.

    [[NSNotificationCenter defaultCenter] addObserver:self                          
                                             selector:@selector(resetTimers:)               
                                                 name:NSSystemClockDidChangeNotification            
                                               object:nil];
    
    [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self
                                                           selector:@selector(resetTimers:)         
                                                               name:NSWorkspaceDidWakeNotification
                                                             object:nil];
    
    0 讨论(0)
提交回复
热议问题