当设备在iOS 7上进入休眠状态时,clock_get_time/mach_absolute_time停止更新

Jay*_*Jay 5 time objective-c ios mach ios7

我的应用程序使用mach_absolute_time来计算自上次触摸事件以来的刻度,并在超过10分钟的空闲时间限制时将用户记录下来.

这一切在iOS 6上运行良好,但我注意到它在iOS 7上运行不正确.具体来说,当iOS 7设备被拔掉(电池电量不足)时,设备似乎停止递增其滴答一旦进入睡眠状态控制台中的这一行(这在大约5分钟不活动后发生):

powerd [47]:睡眠:使用BATT(充电:99%)

因此,当我在10分钟后唤醒设备并使用mach_absolute_time计算滴答时,差异显示仅为5分钟(实际上已经过了10分钟).

奇怪的是,一切正常工作,当设备插入电源时,滴答声继续运行.它从未显示设备在插入时会在控制台日志上休眠(尽管屏幕确实关闭,并且在视觉上与拔出插头时的行为相同).

我也尝试过使用clock_get_time,我在那里遇到了同样的问题.

我可以在iOS 7中做些什么来保持设备进入睡眠状态时的马赫绝对时间?我不想使用,[[NSDate date] timeIntervalSince1970]因为用户可以操纵系统时间并绕过它.

感谢您的任何见解.

Jay*_*Jay 2

事实证明,mach_absolute_time() 的默认行为是在设备进入睡眠状态后停止滴答。在 iOS 6 上,当使用将应用程序置于后台时,我能够将暂停时间延长 10 分钟beginBackgroundTaskWithExpirationHandler。然而,在 iOS 7 中,允许的最长时间被限制为 3 分钟(通过调用发现这一点backgroundTimeRemaining)。这就是为什么我在 iOS 7 上看到时钟停止,但在 iOS 6 上却没有。

今天偶然发现了这个答案,这似乎很有希望。

- (time_t)uptime {
    struct timeval boottime;
    int mib[2] = {CTL_KERN, KERN_BOOTTIME};
    size_t size = sizeof(boottime);
    time_t now;
    time_t uptime = -1;
    (void)time(&now);
    if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0) {
        uptime = now - boottime.tv_sec;
    }
    return uptime;
}
Run Code Online (Sandbox Code Playgroud)

time() 在设备睡眠时继续递增,但当然可以由操作系统或用户操纵。然而,当系统时钟改变时,内核启动时间(系统上次启动的时间戳)也会改变,因此即使这两个值都不固定,但它们之间的偏移量是固定的。