I am trying to update a SwiftUI Image very frequently. That image view is clickable and gets a highlight if selected.
When using an NSTimer with a short interval (0.25 seconds) for the image update, my SwiftUI view does not respond properly to user clicks anymore - clicks are only caught intermittently. If I set the timer interval to 1 second, things would work fine, however, that's not possible in my specific situation.
How can I ensure that my SwiftUI Image's onTapGesture works smoothly even with a high timer frequency?
The timer is declared as such:
let timer = Timer(timeInterval: 0.5, repeats: true, block: { [weak self] timer in
guard let strongSelf = self else {
timer.invalidate()
return
}
// updating an observable object here which will be propagated to the ScreenElement view below
})
timer.tolerance = 0.2
RunLoop.current.add(timer, forMode: .common)
Then I have the SwiftUI view declared as such:
struct ScreenElement: View {
var body: some View {
VStack(alignment: .center, spacing: 12)
{
Image(nsImage: screen.imageData)
.resizable()
.aspectRatio(174/105, contentMode: .fit)
.background(Asset.gray900.swiftUIColor)
.cornerRadius(12)
Text(screen.name)
}
.padding(EdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8))
.onTapGesture {
// modify data source and mark this current element as the highlighted (selected) one
}
}
}
What I have tried:
I tried to move the timer to a background thread which didn't really work and/or caused more problems than it solved. Additionally, I tried to increase the timer interval, which, however, is not feasible in my use case since it has to be a very high refresh rate.
Some further considerations I had but couldn't answer:
Is it maybe possible that SwiftUI just doesn't support a frequent refresh of 4x per second? Or did I maybe use the wrong UI Element to handle the tap gesture in my particular case? Or is it just not possible to have a timer with such frequent updates since it overloads the main thread?
Any help will be greatly appreciated!
The following works fine on an iPhone and Mac, all taps are recognised and it's updating at 10 times per second:
Is there something else you're possibly doing that is blocking the main queue?