foxpaul
foxpaul

Reputation: 67

SwiftUI & Scheduled timers

I'm building an app with SwiftUI with a stop watch functionality. The TimedSession class has a var timer: Timer computed property like this:

Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { timer in
            guard let time = self.currentTime else {
                print("no current time")
                return
            }

            if self.status != .running {
                timer.invalidate()

                return
            }

            time.duration += 1

            self.objectWillChange.send()
        }

this works well until I start to interact with other parts of the UI, like a scrollview. It's not just that the timer UI is locked, but the block: callbck on scheduledTimer isn't being executed.

What's the best way to put the callback block into the background? I've tried with GCD but no good so far.

Upvotes: 3

Views: 2491

Answers (1)

Asperi
Asperi

Reputation: 258217

Scheduled Timer works by default in .default run loop mode, but during user interaction, like scrolling, a run loop works in different tracking mode.

The solution is set up Timer for all standard modes, named .common, like below

// just create non attached timer
let timer = Timer(timeInterval: 0.01, repeats: true) { timer in
            guard let time = self.currentTime else {
                print("no current time")
                return
            }

            if self.status != .running {
                timer.invalidate()

                return
            }

            time.duration += 1

            self.objectWillChange.send()
        }

...

init() {
   // Start timer in run-loop on common modes
   RunLoop.main.add(timer, forMode: .common)
}

Upvotes: 3

Related Questions