Skip to content

MVVM in SwiftUI – Design Pattern

Harnessing design patterns or architectural patterns in SwiftUI not only streamlines your app development process but also ensures your code is easier to manage and maintain. Among these, the Model-View-ViewModel (MVVM) pattern stands out for its effectiveness in separating concerns, enhancing code testability, and simplifying the UI code from the business logic. Let’s explore how the MVVM pattern functions in the context of SwiftUI, likened to the coordination and planning of a dinner party.

The MVVM Pattern: A Culinary Analogy

Picture yourself as a chef orchestrating a grand dinner party. Your pantry stocked with ingredients (the Model) is the foundation of your feast, encompassing everything from veggies to spices. The dishes you meticulously prepare in the kitchen (the ViewModel) are tailored creations, blending ingredients with culinary techniques. Finally, the guests at your table (the View) eagerly await, ready to savor the meal presented before them, yet unaware of the kitchen’s hustle.

In SwiftUI, this narrative translates seamlessly. The Model is your app’s data and business logic, akin to raw ingredients waiting to be transformed. The ViewModel, much like the chef, takes these ingredients, whips up a dish applying specific techniques (or business logic), and decides how the meal (data) should be served. The View, mirroring the dinner party guests, presents this data in a user-friendly manner, offering an interface for users to interact with the app.

This delineation ensures a manageable app architecture, with the ViewModel acting as a mediator to process data, allowing the View to focus solely on presentation. It’s a pattern that not only promises a well-structured codebase but also aligns with SwiftUI’s declarative UI paradigm, making it a favored choice among developers for building scalable and maintainable apps.

Implementing MVVM in SwiftUI: An Example

Let’s put theory into practice with a simple MVVM example in SwiftUI, focusing on a list of people with the ability to dynamically add a new person.

Model

The Model represents the basic data structure:

struct Person {
    var name: String
    var age: Int
}

ViewModel

The ViewModel manages the data and prepares it for presentation:

@Observable class PersonListViewModel {
    var persons = [Person]()
    
    func addPerson(name: String, age: Int) {
        let newPerson = Person(name: name, age: age)
        persons.append(newPerson)
    }
}

Mock Data

Mock data simulates a dataset for initial display:

struct MockData {
    static let persons = [Person(name: "Ali", age: 18), Person(name: "Jane", age: 22)]
}

View

The View displays the data, allowing user interaction:

struct ContentView: View {
    var viewModel = PersonListViewModel()

    var body: some View {
        VStack {
            List(viewModel.persons, id: \.name) { person in
                Text("\(person.name), Age: \(person.age)")
            }
            .onAppear {
                if viewModel.persons.isEmpty {
                    viewModel.persons = MockData.persons
                }
            }
            
            Button("Add Alex, 30") {
                viewModel.addPerson(name: "Alex", age: 30)
            }
        }
    }
}

If you want to learn about other App Design Patterns in SwiftUI, Read this Guide

 

 

 

 

Back To Top