iOS real monotonic clock other than mach_absolute_time()

Viewed 5900

My iOS app needs a custom clock that is synchronized with my server's clock all the time. All the synchronization logic is done.

My clock is based on mach_absolute_time() from which you can calculate the elapsed time since the device was booted. The problem is that when the device goes into sleep mode (by pressing the screen lock key and having no app running in background) the mach time ticking is paused. When the phone is awakened the mach time ticking resumes but it will not account for the time that the phone has been asleep.

This is how I calculate elapsed time since boot (but it won't account for the time the device is asleep)

- (long long) elapsedTimeMillis {
    uint64_t elapsedTimeNano = 0;

    mach_timebase_info_data_t timeBaseInfo;
    mach_timebase_info(&timeBaseInfo);

    elapsedTimeNano = mach_absolute_time() * timeBaseInfo.numer / timeBaseInfo.denom;
    return (long long)(elapsedTimeNano / 1000000);
}

And this has exactly the same results:

- (long long) elapsedTimeMillis {
    clock_serv_t cclock;
    mach_timespec_t mts;

    host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
    clock_get_time(cclock, &mts);
    mach_port_deallocate(mach_task_self(), cclock);

    return mts.tv_nsec / 1000000 + mts.tv_sec * 1000;
}

NSDate, CFAbsoluteTimeGetCurrent() or alike are not an option because they are affected by device time being sync'ed or manually changed by the user.

Is there ANY way to get time in iOS from a non-stop ticking clock that won't jump back or forth?

2 Answers

There is now a mach_continuous_time function that includes time while the system is asleep:

Returns current value of a clock that increments monotonically in tick units (starting at an arbitrary point), including while the system is asleep.

Note that it returns the time in ticks, which is inconvenient. You can instead use clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW) to get nanoseconds.

Here's a complete example in Swift:

import Foundation

let elapsed_time_nanos = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW)

(I don't think it was available back when this question was asked. I'm not sure with which iOS version it was introduced exactly, but it's there on at least iOS 15.)

Related