Time change notification (hours and minutes) in objc

906 Views Asked by At

Is there a best practice to obtain a notification when the time changes?

I'm using a NSTimer that checks every 0,002 secs if the time is changed (hours and minutes, not seconds and milliseconds) to maintain in sync a label in my app with the phone clock every minute.

I'd hope there is a better solution.

Thank you

2

There are 2 best solutions below

0
On

Set a recurring timer starting at the next whole minute:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)        

    let nextMinuteDate =  NSCalendar.currentCalendar().nextDateAfterDate(NSDate(), matchingUnit: .Second, value: 0, options: [.MatchNextTime])!
    self.minuteDidChangeTimer = NSTimer(fireDate: nextMinuteDate, interval: 60.0, target: self, selector: "minuteDidChangeTimer:", userInfo: nil, repeats: true)
    NSRunLoop.currentRunLoop().addTimer(self.minuteDidChangeTimer, forMode: NSDefaultRunLoopMode)

    :
}

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)

    self.minuteDidChangeTimer.invalidate()
    self.minuteDidChangeTimer = nil

    :
}

You might also want to update your UI in response to UIApplicationSignificantTimeChangeNotification for major, unexpected changes, i.e. "change to a new day (midnight), carrier time update, and change to or from daylight savings time".

2
On

If you just want to update when the minute changes, this should do the trick:

NSDate *date = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *dateComponents = [calendar components:NSHourCalendarUnit fromDate:date];
[self performSelector:@selector(minuteHasChanged) withObject:nil afterDelay:(60 - dateComponents.minute)];

And, if you can be certain to only call this method exactly once then you could do something like this:

- (void)minuteHasChanged {
    //do stuff

    NSDate *date = [NSDate date];
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *dateComponents = [calendar components:NSHourCalendarUnit fromDate:date];
    [self performSelector:@selector(minuteHasChanged) withObject:nil afterDelay:(60 - dateComponents.minute)];
}