SwiftUI/SpriteKit项目TestFlight下APP上次活跃时间间隔计算错误
问题根因
你使用的CACurrentMediaTime()本质是设备CPU活跃运行时长的换算值,设备进入休眠状态时该计时会自动暂停,不会统计休眠时间段的时长。
Xcode连接真机调试时,设备处于充电状态会默认关闭自动休眠,CPU持续活跃,因此测试结果符合预期;脱离Xcode进行TestFlight测试时,应用进入后台后设备会自动进入休眠状态,CACurrentMediaTime()的计时增速远慢于实际时间流逝速度,就会出现实际后台停留10分钟、计算结果仅1分钟的偏差。
修复方案
替换为不受设备休眠影响的系统墙上时间Date进行间隔计算即可,同时调整时间保存的时机减少误差:
- 应用进入后台的瞬间直接保存当前时间,避免定时器最后一次触发和应用实际切后台之间的时间差
- 应用返回前台时直接用当前时间和保存的后台时间做差,就能拿到准确的后台停留时长
- 如果需要覆盖应用被系统主动杀后台的场景,可以将保存的时间持久化写入
UserDefaults
调整后代码示例
SceneDelegate 相关代码
func sceneWillResignActive(_ scene: UIScene) { // 销毁定时器 MainData.appWideTimer?.invalidate() MainData.appWideTimer = nil // 切后台瞬间保存当前时间 MainData.oldTime = Date() } func sceneDidBecomeActive(_ scene: UIScene) { // 回到前台立刻计算准确的后台停留时长 let backgroundDuration = Date().timeIntervalSince(MainData.oldTime) // 这里的backgroundDuration就是准确的后台停留秒数,可直接使用 // 重启定时器 mainData.startTheTimer() }
定时器回调代码
@objc func updateClock() { let now = Date() let timeSinceLastTick = now.timeIntervalSince(oldTime) // 其他定时器业务逻辑 oldTime = now }
如果你的业务场景需要避免用户手动修改系统时间带来的误差,可以额外增加服务端时间同步校验逻辑,本地时间统计的场景下上述方案已经可以覆盖绝大多数需求。
内容的提问来源于stack exchange,提问作者West1
相关产品推荐
相关产品推荐

