CD-3 CD-3 - 1 month ago 10
Swift Question

Creating a stopwatch in swift

I have tried searching other answers and I cannot find one that applies to my scenario. I am writing a game in swift and want to create a stopwatch that determines how the long the player is playing. When the user touches down, the stopwatch will start and when a certain action happens, then the timer stops and resets. I'd like to use minutes, seconds, milliseconds (i.e. 00:00.00).

Currently, the time function kind of works. It doesn't start at 0, it starts at the current seconds in time (I know thats when I start it, but I don't know how to start it at 0). It also only updates when I touch the screen, I need it to count from 00:00.00 and update on its own until the cancel action is fired.

Thank you for your time.

Here is what I have so far:

class GameScene: SKScene {

var activeTimer = SKLabelNode()
//var bestTime = SKLabelNode()

var startTime = TimeInterval()
//var currentTime = TimeInterval()
//var countingTime = TimeInterval()
var updateTimerAction = SKAction()


override func didMove(to view: SKView) {

activeTimer = self.childNode(withName: "active_timer") as! SKLabelNode
//bestTime = self.childNode(withName: "best_time") as! SKLabelNode

startTime = TimeInterval(Calendar.current.component(.second, from:Date()))
updateTimerAction = SKAction.sequence([SKAction.run(updateTimer), SKAction.wait(forDuration: 1.0)])
}


func startGame() {
// Other code
startGameTimer()
}

func resetGame() {
// Other code
stopGameTimer()
}

func startGameTimer() {
run(SKAction.repeatForever(updateTimerAction), withKey: "timer")
}

func updateTimer() {
activeTimer.text = stringFromTimeInterval(interval: startTime) as String
}

func stringFromTimeInterval(interval: TimeInterval) -> NSString {

let ti = NSInteger(interval)

let ms = Int((interval.truncatingRemainder(dividingBy: 1)) * 1000)

let seconds = ti % 60
let minutes = (ti / 60) % 60

return NSString(format: "%0.2d:%0.2d.%0.2d",minutes,seconds,ms)
}


func stopGameTimer() {
removeAction(forKey: "timer")
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

startGame()

for touch in touches {
// other code
}
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

for touch in touches {
// other code
}
}


override func update(_ currentTime: TimeInterval) {

updateTimer()

if <action> {
// stop timer and reset game
resetGame()
}
}

Answer Source

Instead of using a TimeInterval object, it might be better to use a Timer object which calls a function that increments the value of a label (or an internal variable) from 0 onwards accordingly after every 1 second(or can be made lesser). And for stopping the clock just call the Timer object's invalidate function. Check the documentation for more info: https://developer.apple.com/documentation/foundation/timer