如何使 NSTimer 更准确?
How to make NSTimer more accurate?
在我的应用程序中,我在视图控制器上放置了一个标签,我希望该标签显示一个每毫秒递增 1 的数字。 (我知道我可以每秒更新 1000,但我希望它看起来平滑)
@IBOutlet var label: UILabel!
var number = 0
var timer: NSTimer!
override func viewDidLoad() {
super.viewDidLoad()
timer = NSTimer.scheduledTimerWithTimeInterval(0.001, target: self, selector: Selector("addNumber"), userInfo: nil, repeats: true)
}
func addNumber () {
number++
label.text = number.description
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
timer?.invalidate()
}
代码对我来说看起来都很合理,但是当我 运行 应用程序时,我看到数字每秒增加大约 50,而不是每秒 1000。这个错误是无法接受的!
没想到,当我锁屏几秒再解锁的时候,数字突然增加了几千!
我认为这是因为我在计时器触发时更新 UI,因此需要更多时间。但是我该如何解决这个问题?
你的问题是询问如何使 NSTimer
更准确,我有一些坏消息:你不能。 NSTimer
的合理预期是它每秒可以调用约 30 次,如果幸运的话,每秒可以调用约 60 次。没关系。
从实际的角度考虑:显示最多只能每秒更新 60 次,因此没有必要更频繁地向用户提供反馈。
如果您试图最大限度地利用硬件并依靠它尽可能快地启动,那么您将在较旧和较慢的硬件上遇到问题,它可能每秒只能启动约 20 次。
依靠 NSTimer
的时间间隔会让你很快陷入困境。
由于您要查找的是毫秒数,因此您可以设置一个开始时间,每次调用您的函数时,查看自开始时间以来的毫秒数,这就是经过的毫秒数。
您当前的方法会执行 Apple 文档中规定的所有操作:number
只是该方法被调用的次数(不是经过的毫秒数)。
基于@Fennelouski 的回答,我建议您换成 CADisplayLink,它非常适合此类任务。它会在每次屏幕更新时调用您的方法(或每 2 次或 3 次,或任何您设置的 frameInterval
属性)。它还有一个 timestamp
变量,你可以用它来计算已经过去了多少时间并相应地更新你的标签
在我的应用程序中,我在视图控制器上放置了一个标签,我希望该标签显示一个每毫秒递增 1 的数字。 (我知道我可以每秒更新 1000,但我希望它看起来平滑)
@IBOutlet var label: UILabel!
var number = 0
var timer: NSTimer!
override func viewDidLoad() {
super.viewDidLoad()
timer = NSTimer.scheduledTimerWithTimeInterval(0.001, target: self, selector: Selector("addNumber"), userInfo: nil, repeats: true)
}
func addNumber () {
number++
label.text = number.description
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
timer?.invalidate()
}
代码对我来说看起来都很合理,但是当我 运行 应用程序时,我看到数字每秒增加大约 50,而不是每秒 1000。这个错误是无法接受的!
没想到,当我锁屏几秒再解锁的时候,数字突然增加了几千!
我认为这是因为我在计时器触发时更新 UI,因此需要更多时间。但是我该如何解决这个问题?
你的问题是询问如何使 NSTimer
更准确,我有一些坏消息:你不能。 NSTimer
的合理预期是它每秒可以调用约 30 次,如果幸运的话,每秒可以调用约 60 次。没关系。
从实际的角度考虑:显示最多只能每秒更新 60 次,因此没有必要更频繁地向用户提供反馈。
如果您试图最大限度地利用硬件并依靠它尽可能快地启动,那么您将在较旧和较慢的硬件上遇到问题,它可能每秒只能启动约 20 次。
依靠 NSTimer
的时间间隔会让你很快陷入困境。
由于您要查找的是毫秒数,因此您可以设置一个开始时间,每次调用您的函数时,查看自开始时间以来的毫秒数,这就是经过的毫秒数。
您当前的方法会执行 Apple 文档中规定的所有操作:number
只是该方法被调用的次数(不是经过的毫秒数)。
基于@Fennelouski 的回答,我建议您换成 CADisplayLink,它非常适合此类任务。它会在每次屏幕更新时调用您的方法(或每 2 次或 3 次,或任何您设置的 frameInterval
属性)。它还有一个 timestamp
变量,你可以用它来计算已经过去了多少时间并相应地更新你的标签