xcode 以毫秒为单位的快速计时器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30983111/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Swift timer in milliseconds
提问by grape1
I want to change the timer every millisecond but it doesnt work as expected.
我想每毫秒更改一次计时器,但它没有按预期工作。
NSTimer.scheduledTimerWithTimeInterval(0.001, target: self, selector: Selector("advanceTimer:"), userInfo: nil, repeats: true);
func advanceTimer(timer: NSTimer){
self.time += 0.001;
let milliseconds = self.time * 100;
let remaingMilliseconds = Int((milliseconds % 1000) / 10);
let seconds = Int((milliseconds / 1000) % 60)
let strSeconds = String(format: "%02d", seconds)
let strFraction = String(format: "%02d", remaingMilliseconds)
timerText.text = "\(strSeconds):\(strFraction)";
}
The result is
结果是
The timer change up to 100 in the millisecond part (00:100) and then change to 01:00 = 40 real secs
计时器在毫秒部分 (00:100) 更改为 100,然后更改为 01:00 = 40 实秒
Duncan approach:
邓肯方法:
var time: NSTimeInterval = 0;
var startTime: NSTimeInterval = 0;
//And your timer method...
func advanceTimer(timer: NSTimer){
//Total time since timer started, in seconds
self.time = NSDate.timeIntervalSinceReferenceDate() - startTime
println(self.time);
//The rest of your code goes here
}
override func didMoveToView(view: SKView) {
// Set anchor point
self.anchorPoint = CGPointMake(0.5, 0.5);
var startTime: NSTimeInterval
//Sart the timer
startTime = NSDate.timeIntervalSinceReferenceDate()
NSTimer.scheduledTimerWithTimeInterval(0.02,
target: self,
selector: Selector("advanceTimer:"),
userInfo: nil,
repeats: true)
}
Result: 456680125.54539 the first print
结果:456680125.54539 第一次打印
回答by Duncan C
As Martin says in his comment, timers have a resolution of 50-100 ms (0.05 to 0.1 seconds). Trying to run a timer with an interval shorter than that will not give reliable results. Also, timers are not realtime. They depend on the run loop they are attached to, and if the run loop gets busy, the firing of the timer gets delays.
正如马丁在评论中所说,计时器的分辨率为 50-100 毫秒(0.05 到 0.1 秒)。尝试以比该间隔更短的间隔运行计时器将无法提供可靠的结果。此外,计时器不是实时的。它们依赖于它们所连接的运行循环,如果运行循环变得忙碌,定时器的触发就会延迟。
Instead of trying to increment a counter each time your timer fires, record the start time when you initiate the timer, and then do some math to figure out how much time has transpired:
不要在每次计时器触发时都尝试递增计数器,而是在启动计时器时记录开始时间,然后进行一些数学运算来计算已经发生了多少时间:
var startTime: NSTimeInterval
//Sart the timer
startTime = NSDate.timeIntervalSinceReferenceDate()
NSTimer.scheduledTimerWithTimeInterval(0.02,
target: self,
selector: Selector("advanceTimer:"),
userInfo: nil,
repeats: true)
//And your timer method...
func advanceTimer(timer: NSTimer)
{
//Total time since timer started, in seconds
self.time = NSDate.timeIntervalSinceReferenceDate() - startTime
//The rest of your code goes here
}
EDIT:
编辑:
The Swift 3 version of this code looks like this:
此代码的 Swift 3 版本如下所示:
(Written as a view controller in a test project)
(在一个测试项目中写成一个视图控制器)
class ViewController: UIViewController {
weak var timer: Timer?
var startTime: Double = 0
var time: Double = 0
@IBOutlet weak var timeValueLabel: UILabel!
/*
When the view controller first appears, record the time and start a timer
*/
override func viewDidAppear(_ animated: Bool) {
startTime = Date().timeIntervalSinceReferenceDate
timer = Timer.scheduledTimer(timeInterval: 0.05,
target: self,
selector: #selector(advanceTimer(timer:)),
userInfo: nil,
repeats: true)
}
//When the view controller is about to disappear, invalidate the timer
override func viewWillDisappear(_ animated: Bool) {
timer?.invalidate()
}
func advanceTimer(timer: Timer) {
//Total time since timer started, in seconds
time = Date().timeIntervalSinceReferenceDate - startTime
//The rest of your code goes here
//Convert the time to a string with 2 decimal places
let timeString = String(format: "%.2f", time)
//Display the time string to a label in our view controller
timeValueLabel.text = timeString
}
}