Search code examples
iosswifttimer

how to create a timer that has an accuracy of 0.1 second?


I have tried to add a timer in a drawing app so that it can track the time of the drawing. When the user starts drawing(touches begin), the timer starts to time. Then when the user lifts the pen or finger, the timer stops. I wanted to have the accuracy of the timer to be 0.1seconds.

Following are the code I have tried but can only have 1 as the smallest internal.

@objc func startTiming () {
         time += 1.0
     }
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    //start timing
    timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(TrailingCanvas.startTiming), userInfo: nil, repeats: true)
    let touch = touches.first
    startingPoint = touch?.preciseLocation(in: self)
    TrailUserInputX.append(startingPoint.x)
    TrailUserInputY.append(startingPoint.y)
    print("\(String(describing: touch?.force))")
    }

}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    //timer
    timer.invalidate()
    endingPointX = TrailUserInputX.last
    if endingPointX != nil {
        UserMatchingLocation.append(endingPointX!)
    }
}

Solution

  • Timers are not suitable for this job. You can get a much more accurate time recording the time (as a Date object) at touchesBegan, and seeing how much time has passed since now in touchesEnded.

    var lastTouchesBeganDate: Date?
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        lastTouchesBeganDate = Date()
    
        let touch = touches.first
        startingPoint = touch?.preciseLocation(in: self)
        TrailUserInputX.append(startingPoint.x)
        TrailUserInputY.append(startingPoint.y)
        print("\(String(describing: touch?.force))")
        }
    
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        time += lastTouchesBeganDate?.timeIntervalSinceNow ?? 0
    
        endingPointX = TrailUserInputX.last
        if endingPointX != nil {
            UserMatchingLocation.append(endingPointX!)
        } }