SwiftUI, Apple's modern framework for building user interfaces, has brought a fresh approach to iOS app development. When combined with the Model-View-ViewModel (MVVM) architectural pattern, it allows for creating clean, modular, and testable code. In this tutorial, we will explore how to implement MVVM in a SwiftUI application step by step.
Define the ModelIn MVVM, the Model represents the data and business logic of your application. For this tutorial, let's create a simple Model to manage a list of tasks.
import Foundation
struct Task: Identifiable {
let id = UUID()
var title: String
var completed: Bool
}
class TaskManager: ObservableObject {
@Published var tasks: [Task] = []
func addTask(_ title: String) {
let task = Task(title: title, completed: false)
tasks.append(task)
}
// Add other methods for managing tasks
}
Build the ViewModel
The ViewModel serves as the bridge between the Model and the View, providing data and handling user interactions.
import Foundation
import SwiftUI
class TaskViewModel: ObservableObject {
@Published private var taskManager = TaskManager()
@Published var newTaskTitle = ""
var tasks: [Task] {
taskManager.tasks
}
func addTask() {
guard !newTaskTitle.isEmpty else { return }
taskManager.addTask(newTaskTitle)
newTaskTitle = ""
}
// Add other ViewModel logic here
}
Create the View
In SwiftUI, the View is responsible for displaying data and capturing user interactions. Create a View that displays the list of tasks and allows the user to add new ones.
import SwiftUI
struct TaskListView: View {
@ObservedObject var viewModel: TaskViewModel
var body: some View {
NavigationView {
VStack {
TextField("Add a new task", text: $viewModel.newTaskTitle)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button(action: viewModel.addTask) {
Text("Add Task")
}
.padding()
List(viewModel.tasks) { task in
Text(task.title)
}
}
.navigationTitle("Task List")
}
}
}
Connect the View and ViewModel
In your app's entry point (e.g., App.swift), create an instance
of the
TaskViewModel
and inject it
into your view.
import SwiftUI
@main
struct MVVMTutorialApp: App {
@StateObject var viewModel = TaskViewModel()
var body: some Scene {
WindowGroup {
TaskListView(viewModel: viewModel)
}
}
}
Testing and Running the App
Build and run your project. You should be able to add tasks, and they will appear in the list. The text field should clear after adding a task.
ConclusionYou've successfully implemented MVVM architecture in a SwiftUI application. MVVM encourages separation of concerns, making your code more maintainable and testable. You can extend this example by adding more features, incorporating data persistence, or even using Combine to handle asynchronous operations. MVVM in SwiftUI is a powerful combination for building robust and scalable iOS applications.