Measuring Time Accurately in Swift for Comparison

2019-01-18 00:41发布

I need to be able to record reaction time, from when the screen loads or the question label refreshes until the user taps a number button. I'm not finding documentation from Apple on this to be very helpful. NSDate is not accurate enough, I need to measure to milliseconds at least. mach_absolute_time seems to be favored by game designers because it is internally consistent, but it won't work for this application because I need to compare data across devices, and mach_absolute_time is CPU dependent time. This Apple Dev Q&A suggests using NanosecondsToAbsolute and DurationToAbsolute but it's in obj-c and I can't find a swift equivalent documentation.

Is there a swift version of NanosecondsToAbsolute and DurationToAbsolute that I'm just not finding? Some other way to do this consistently?

Here's the code I'm trying to add the times to:

class EmotionQuestionsViewController: UIViewController{

    override func viewDidLoad() {
        super.viewDidLoad()

//mark "startTime" when view loads
    }

    @IBOutlet var questionLabel: UILabel!
    var timeResultsStack = [String]()

    var questionsStack = ["HAPPY", "ANXIOUS"]
    var questionResultsStack = [String]()
    var questionStackArrayIndex = 1

    @IBAction func RecordValueFromNumericalScaleOneToSeven(sender: UIButton) {

//mark durration time as currentTime - startTime, append to timeResultsStack

        let value = sender.currentTitle!
        questionResultsStack.append(value)

        if questionResultsStack.count < questionsStack.count{
            self.questionLabel.text = "how \(questionsStack[questionStackArrayIndex]) are you right now?"

//mark startTime when label is changed

            self.questionStackArrayIndex++

        }
        else{
            self.performSegueWithIdentifier("showResults", sender: nil)

        }
    }

标签: ios swift time
3条回答
对你真心纯属浪费
2楼-- · 2019-01-18 01:29

As already said, the precision of NSDate() is probably good enough for your purpose. Just for the sake of completeness, mach_absolute_time() from the referenced Technical Q&A QA1398 works in Swift as well:

let t1 = mach_absolute_time()
// do something
let t2 = mach_absolute_time()

let elapsed = t2 - t1
var timeBaseInfo = mach_timebase_info_data_t()
mach_timebase_info(&timeBaseInfo)
let elapsedNano = elapsed * UInt64(timeBaseInfo.numer) / UInt64(timeBaseInfo.denom);
print(elapsedNano)

Possible advantages of this method:

  • Calling mach_absolute_time() seems to be much faster than calling NSDate().timeIntervalSinceReferenceDate, so this method might be better suited to measure extremely short intervals.
  • The value of NSDate() changes if the clock is adjusted, mach_absolute_time() does not have this problem.
查看更多
看我几分像从前
3楼-- · 2019-01-18 01:34

NSDate is tied to the realtime clock on iOS and Mac devices, and has sub-millisecond accuracy.

Use NSDate's timeIntervalSinceReferenceDate method to convert an NSDate (or the current time) to a double that is the number of seconds since January 1, 2001, including fractional seconds. Once you do that you're free to do math on the doubles that you get back.

查看更多
叛逆
4楼-- · 2019-01-18 01:35

You can use NSTimeInterval to measure time (much better than a timer). You just need to store two dates (two points in time) and subtract endTime - StartTime as follow:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var salesPriceSlider: UISlider!

    var startTime: NSTimeInterval = 0
    var endTime: NSTimeInterval = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        startTime = NSDate().timeIntervalSinceReferenceDate
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    @IBAction func stopTimeAction(sender: AnyObject) {
        endTime = NSDate().timeIntervalSinceReferenceDate
        println((endTime-startTime).time)
    }

}

extension NSTimeInterval {
    var time: String {
        return String(format:"%d:%02d:%02d.%03d", Int(self/3600.0), Int(self/60.0 % 60), Int(self % 60), Int(self*1000 % 1000))
    }
}
查看更多
登录 后发表回答