Build: Simple Counter
A screen that shows a number and two buttons to increase or decrease it using MVVM pattern.
Target UI
------------------- | Simple Counter | ------------------- | | | 0 | | | | [-] [+] | -------------------
------------------- | Simple Counter | ------------------- | | | 0 | | | | [-] [+] | -------------------
import SwiftUI struct ContentView: View { // TODO: Create ViewModel instance here var body: some View { VStack(spacing: 40) { Text("0") // TODO: Bind this to ViewModel's number .font(.largeTitle) HStack(spacing: 60) { Button("-") { // TODO: Call ViewModel to decrease number } .font(.title) Button("+") { // TODO: Call ViewModel to increase number } .font(.title) } } .padding() } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
import SwiftUI class CounterViewModel: ObservableObject { @Published var number: Int = 0 func increase() { number += 1 } func decrease() { number -= 1 } } struct ContentView: View { @StateObject private var viewModel = CounterViewModel() var body: some View { VStack(spacing: 40) { Text("\(viewModel.number)") .font(.largeTitle) HStack(spacing: 60) { Button("-") { viewModel.decrease() } .font(.title) Button("+") { viewModel.increase() } .font(.title) } } .padding() } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
This app uses the MVVM pattern by separating the logic from the view. The CounterViewModel class holds the number and methods to change it. It uses @Published so SwiftUI updates the UI automatically when the number changes.
The ContentView creates a @StateObject instance of the ViewModel. The text showing the number binds to viewModel.number. The buttons call the ViewModel's increase and decrease methods. This keeps the UI simple and the logic in the ViewModel, following MVVM principles.
------------------- | Simple Counter | ------------------- | | | 0 | | | | [-] [+] | -------------------
class CounterViewModel: ObservableObject {
@Published var count = 0
func increment() { count += 1 }
}
struct ContentView: View {
@ObservedObject var viewModel = CounterViewModel()
var body: some View {
VStack {
Text("Count: \(viewModel.count)")
Button("Tap me") {
viewModel.increment()
}
}
}
}class UserViewModel {
@Published var username: String = ""
func updateName(newName: String) {
username = newName
}
}Pass the test and this pattern moves unknown