Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Measuring Time Accurately in Swift for Comparison Across Devices

Tags:

time

ios

swift

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)

        }
    }
like image 350
Lauren G Avatar asked Nov 30 '22 10:11

Lauren G


1 Answers

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.
like image 169
Martin R Avatar answered Dec 05 '22 14:12

Martin R