I have two identical projects. One was written with SwiftUI and the other with UIKit. But while UIKit consumes 5% CPU, SwiftUI consumes 26% CPU. Does anyone know how I can reduce the CPU used by SwiftUI?
My original question was List vs UITableView. But I saw that LazyVStack was much more efficient than List, thanks to @Paulw11. But it's still far behind UITableView.
import SwiftUI
struct ContentView: View {
@State private var progress: Double = 0.0
var body: some View {
VStack {
ScrollView {
LazyVStack {
ForEach(1...1000, id: \.self) { value in
Text("Hello, world!")
}
}
}
Slider(value: $progress, in: 0.0...1.0, step: 0.01)
}
.onChange(of: progress, perform: { value in
print(value)
})
}
}
import UIKit
final class ViewController: UIViewController {
private let array: Array<String> = Array(repeating: "Hello, world!", count: 1000)
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var slider: UISlider!
@IBAction func sliderChanged(_ sender: UISlider) {
print(sender.value)
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
array.count[enter image description here][1]
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath)
cell.textLabel?.text = array[indexPath.row]
return cell
}
}
@hyouuu The most important part is the progress value. Avoid using the @Published value as much as possible in ViewModels. Instead, split the views into subviews and manually set a value to the ViewModel as in the example.
import SwiftUI
import Combine
final class ViewModel: ObservableObject {
var array = Array(1...1000)
var text = "Hello, world!"
var progress: Double = 0.0 {
didSet {
print("new value",progress)
}
}
}
struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
VStack {
Scroll(viewModel: viewModel)
Slide(viewModel: viewModel)
}
}
}
struct Scroll: View {
@StateObject var viewModel: ViewModel
var body: some View {
List {
ForEach(viewModel.array, id: \.self) { value in Text(viewModel.text) }
}
}
}
struct Slide: View {
@StateObject var viewModel: ViewModel
@State var progress:Double = 0.0
var body: some View {
Slider(value: $progress, in: 0.0...1.0, step: 0.01)
.onChange(of: progress) { newValue in
viewModel.progress = newValue
}
}
}