iPhone hardware & user timers getting out of sync over time

406 views Asked by At

I'm trying to detect if the user advances their clock while an app is running. I'm currently doing this by comparing how two timers change: [NSDate timeIntervalSinceReferenceDate] and mach_absolute_time.

The basic algorithm is this:

  • At the start of the app, save startUserClock (timeIntervalSinceReferenceDate) and startSystemClock (mach_absolute_time converted to seconds)
  • Periodically diff the current values of the timers against their respective start values.
  • If the diff's are different (within some margin of error), we should know that the timers are out of sync, which indicates a clock change - theoretically the only time this should be possible is if the user has modified their clock.

However, it seems that mach_absolute_time is growing at a slightly faster rate than timeIntervalSinceReferenceDate. In the short term, this isn't a huge issue, but over time the difference adds up and we start seeing a lot of false positives.

This problem appears to be hardware dependent. I don't see it at all on the iPad 1 I have, but a colleague sees it on his iPad 2 and I see it in the simulator.

I've confirmed that there isn't a problem with my conversion of mach_absolute_time to seconds by replacing it with CACurrentMediaTime (which uses mach_absolute_time under the hood). I've tried changing timeIntervalSinceReferenceDate to other timing methods (ie: CFAbsoluteTimeGetCurrent).

Is there something wrong with my base assumption that the timers should grow at the same rate? My thinking was that unless something is fundamentally wrong they shouldn't get so out of sync - they're both determining time, just starting from different points.

Is there a better way to do this? I need a completely offline solution - we can't assume an internet connection.

2

There are 2 answers

0
Brian Coleman On

You could try using gettimeofday to get the value of the current system time. This returns the time since the epoch.

2
Paul On

In general, timers aren't guaranteed to be in synch. Perhaps they're derived from different sources. Perhaps one is synchronized against a time server.

You only care about sudden changes in the difference between the clocks, not large drifts over time. So compute the rate of change of the difference between the clocks:

T_Diff := initial difference between clocks
T_Time := time as determined by one clock
Repeat forever:
  T_Diff' := new difference between clocks
  T_Time' := new time as determined by one clock

  # Check if time changed
  if abs((T_Diff'-T_Diff)/(T_Time'-T_Time)) > threshold:
    time_changed()

  # Update state
  T_Diff := T_Diff'
  T_Time := T_Time'

  wait_for_next_update()