I want to make a Swift Chart that updates on each frame - I expect to be monitoring a data source that updates constantly. I've made a little demo view to do this, but CPU usage is through the roof - a constant 90%
What can I do to play more nice with SwiftUI and bring the CPU usage down to a more modest level, yet still update at screen refresh rate?
My example is here:
import SwiftUI
import Charts
struct DataPoint: Identifiable {
var id: Int { return x }
let x: Int
let y: Float
}
class ViewModel: ObservableObject {
@Published var data: [DataPoint] = []
init() {
data = _regen()
Task {
await loop()
}
}
func regen() {
data = _regen()
}
func loop() async {
try? await Task.sleep(nanoseconds: 1_000_000_000 / 120)
Task { @MainActor in
regen()
}
await loop()
}
private func _regen() -> [DataPoint] {
let start = Int(Date().timeIntervalSince1970 * 60) % 100
let end = start + 300
let vals: [DataPoint] = (start..<end).map {
DataPoint(x: $0, y: sin(Float($0) / 10.0))
}
return vals
}
}
struct ContentView: View {
@ObservedObject var viewModel: ViewModel = ViewModel()
var body: some View {
VStack {
Chart(viewModel.data) {
LineMark(
x: .value("", $0.x - viewModel.data[0].x),
y: .value("Value", 1-($0.y))
)
}
Chart(viewModel.data) {
LineMark(
x: .value("", $0.x - viewModel.data[0].x),
y: .value("Value", $0.y * 0.2)
)
}
Chart(viewModel.data) {
LineMark(
x: .value("", $0.x - viewModel.data[0].x),
y: .value("Value", $0.y)
)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}