我有两个功能可以衡量手机被锁定或应用程序处于后台的时间:
func saveTimeInBackground(){
startMeasureTime = Int(Date.timeIntervalSinceReferenceDate)
}
func timeOnAppActivated(){
stopMeasureTime = Int(Date.timeIntervalSinceReferenceDate)
elapsedTime = stopMeasureTime - startMeasureTime
seconds = seconds - elapsedTime + 2
if seconds > 0 {
timerLbl.text = "time: \(seconds)"
} else {
seconds = 0
timerLbl.text = "time: \(seconds)"
}
}
然后在viewDidLoad()中我有观察者在应用变为活动/非活动时触发功能:
NotificationCenter.default.addObserver(self, selector: #selector(saveTimeInBackground), name: Notification.Name.UIApplicationWillResignActive, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(timeOnAppActivated), name: Notification.Name.UIApplicationDidBecomeActive, object: nil)
问题是,当应用程序变为活动状态时,差异为2秒(大约),所以我添加了2秒,似乎工作正常,但仅当经过的时间是> 15秒 如果我锁定手机并立即将其解锁,则会丢失5秒或更长时间。例如,如果剩下50秒,当我锁定并立即解锁时,还剩下42秒。
任何人都可以解释一下,我做错了什么?
修改:应用程序的逻辑是:
比赛开始时,两名玩家之间的比赛为60秒。问题是,当其中一个玩家锁定手机时,应用停止测量时间。这样,如果玩家1还剩10秒钟进行移动,则玩家2还剩下50秒。我正在寻找一种可靠的方法来计算时间,即使玩家锁定手机或将应用程序放在后台。
编辑2 :我想我弄清楚问题是什么:我认为这个问题与“秒”是Int,而不是Date和转换时的事实有关它被围捕了。我没有测试它,但是当我解决方案时,我会发布答案。谢谢大家的时间!
答案 0 :(得分:1)
您依赖于无法确保具有任何确切时间的通知的确切时间。这些通知的确切时间到达时间无法保证,您无法做到这一点。正如你所说,即使你的两秒钟修正也是近似的。它可能会在iPhone的不同型号上有所不同,甚至可能在同一iPhone上的不同时间有所不同,具体取决于您检查时iOS的繁忙程度。
更重要的是,当你进入后台时,你不能确定你会留在那里。一旦进入后台,iOS可能会决定随时终止您的应用。
我不确定这里的目标是什么,但我认为你需要重新考虑你想做什么,看看是否有其他方法。你目前的两秒黑客攻击最多会产生一堆其他黑客(比如你提到的15秒门槛)而不会特别准确。然后,当一些iOS更改导致时间发生变化时,它可能会在下一次iOS更新中中断。
答案 1 :(得分:1)
我会使用Date对象来跟踪游戏时间。
func gameStart() {
gameStartDate = Date()
}
func timeOnAppActivated() {
let secondsLeft = 60 - abs(gameStartDate?.timeIntervalSinceNow ?? 0)
if secondsLeft > 0 {
timerLbl.text = "time: \(secondsLeft)"
} else {
timerLbl.text = "time: 0"
}
}
答案 2 :(得分:0)
好的,就像我在问题的编辑2中提到的那样: 第一个问题是因为“秒”是一个Int,然后在从Double转换它时几乎总是增益或失去。
但主要的问题是,当应用程序进入后台时,我不得不使计时器无效。
所以现在当应用程序获得将进入后台的通知然后在进入前台时启动它时,计时器无效,一切正常。
答案 3 :(得分:-1)
要在按钮单击时正确调用这些方法。在后台释放一些资源可能会有延迟。