DEV Community

garry
garry

Posted on

Testing Timer Accuracy on Different iOS Devices

You Cannot Trust the Simulator

The iOS Simulator runs on your Mac's CPU. Timers in the simulator are suspiciously accurate because they are backed by a desktop processor that is not juggling cellular radios, thermal throttling, or aggressive power management. Real devices lie in different and more interesting ways.

My Testing Methodology

When I built BoxTime, I needed to verify that the timer was accurate across a range of devices. I set up a simple test: start a 3-minute round, compare the app's completion time against an external reference (a stopwatch on another device).

The Test Harness

#if DEBUG
class TimerAccuracyLogger {
    private var roundStartTime: Date?
    private var expectedDuration: TimeInterval = 0

    func roundStarted(expectedDuration: TimeInterval) {
        self.roundStartTime = Date()
        self.expectedDuration = expectedDuration
    }

    func roundEnded() {
        guard let start = roundStartTime else { return }
        let actual = Date().timeIntervalSince(start)
        let drift = actual - expectedDuration
        print("Expected: \(expectedDuration)s, Actual: \(String(format: "%.4f", actual))s, Drift: \(String(format: "%.4f", drift))s")
    }
}
#endif
Enter fullscreen mode Exit fullscreen mode

I ran this across five devices: iPhone SE (2nd gen), iPhone 12, iPhone 14 Pro, iPhone 15, and an iPad Air. Each device ran a full 12-round, 3-minute workout with 1-minute rest periods.

Results

Device Per-Round Drift Total Drift (36 min)
iPhone SE (2nd gen) < 1ms < 12ms
iPhone 12 < 1ms < 12ms
iPhone 14 Pro < 0.5ms < 6ms
iPhone 15 < 0.5ms < 6ms
iPad Air (5th gen) < 1ms < 12ms

With the absolute-time-anchored approach (computing remaining time from Date() rather than counting ticks), drift is negligible on all devices. The sub-millisecond drift comes from the time between the Date() call and the actual notification/haptic firing.

Where Things Go Wrong

Thermal Throttling

I ran the test while the iPhone SE was charging in a warm room. The device thermal-throttled, and frame rates dropped. But the timer accuracy was unaffected because it is not tied to frame rate. The display update was choppy, but the round ended at the correct time.

Low Power Mode

Low Power Mode reduces CPU frequency and limits background activity. Timer accuracy was unaffected in the foreground. However, if the app moves to the background while Low Power Mode is active, iOS is more aggressive about suspending it. The local notification fallback handles this.

App Backgrounding

This is the real threat to accuracy. When the app goes to the background, iOS can suspend it within seconds. My test:

  1. Start a 3-minute round
  2. Switch to Safari for 30 seconds
  3. Return to BoxTime

Result: the timer correctly shows the right remaining time because it recalculates from the absolute end time on every frame after returning to foreground.

func sceneDidBecomeActive(_ scene: UIScene) {
    // Timer automatically shows correct time because remainingTime
    // is computed from Date(), not from accumulated ticks
    // No manual state restoration needed for the display
}
Enter fullscreen mode Exit fullscreen mode

Edge Case: System Clock Changes

What if the user changes their system clock mid-workout? This could theoretically break an absolute-time approach. I handle it with ProcessInfo.processInfo.systemUptime as a sanity check:

func validateTimeConsistency() {
    let wallClockElapsed = Date().timeIntervalSince(workoutStartDate)
    let uptimeElapsed = ProcessInfo.processInfo.systemUptime - workoutStartUptime

    // If wall clock and uptime disagree by more than 2 seconds,
    // the system clock was probably changed
    if abs(wallClockElapsed - uptimeElapsed) > 2.0 {
        // Fall back to uptime-based calculation
        recalibrateFromUptime()
    }
}
Enter fullscreen mode Exit fullscreen mode

This is an edge case I have never seen in production, but it costs five lines of code to handle.

The Takeaway

Timer accuracy on iOS is a solved problem if you use the right architecture. Anchor to absolute time, use CADisplayLink for display updates, and handle backgrounding gracefully. Testing on real devices confirms what the theory predicts -- the approach works across the full range of iOS hardware.

BoxTime has been used for thousands of workout sessions with zero reported timing issues.

Top comments (0)