MVVM in SwiftUI

DevTechie Inc
Dec 7, 2022


Photo by Glen Carrie on Unsplash

MVVM (Model View ViewModel) is a popular structural design pattern. MVVM puts objects into three groups.

Models: Model is used to hold app’s data. Model’s are usually simple structs or classes representing the basic data structure for apps. Models are UI independent.

Views: View is the visual element of the app and they provide interaction point for users of the app.

View models: ViewModel is used to transform model data into values that can be passed on and displayed on a view. ViewModels are usually defined as classes, so they can be passed around as references. ViewModels are used to bind Models to the Views.

In order to solidify our understanding, let’s look at an example. We will build DevTechie courses app.

Model
In order to get started, we need a data structure which will represent data that we want to present to our users. In this case it’s a DevTechie course struct. This struct will have two properties, name and course length. Since we are building a SwiftUI app, we also need to make sure that each object can be identified uniquely and for that, we will make our struct to conform to an Identifiable protocol.

Our model will look like this:

struct DevTechieCourse: Identifiable {
    let id = UUID()
    var name: String
    var courseLength: Int
}
ViewModel
In MVVM, the View comes after the Model but in practice we need to create ViewModel in order to pass Model information into the View.

ViewModel is responsible for collecting the data and transforming it in a way which can be presented on the view. ViewModels also notifies the view of data changes so the view knows when to update itself.

In SwiftUI world, ViewModel uses @Published modifier to notify changes to the view. Published modifier requires ViewModel class to conform to the ObservableObject protocol.

In our example, we will create an array of DevTechieCourses as a published property.

class DevTechieCourseViewModel: ObservableObject {
    @Published var courses = [DevTechieCourse]()
}
Let’s also create a function to populate example data for our app to use.

class DevTechieCourseViewModel: ObservableObject {
    @Published var courses = [DevTechieCourse]()
    
    func populate() {
        courses = [
            .init(name: "Mastering SwiftUI 4 by Example", courseLength: 120),
            .init(name: "Practical Machine Learning in iOS", courseLength: 90),
            .init(name: "Build DisneyPlus Clone in SwiftUI", courseLength: 180)
        ]
    }
}
View
Views are used to display app’s data to the user. Views are also the interaction points for our users. In SwiftUI, data drives the UI meaning changes in data updates the view automatically. We do this by creating instance of ViewModel marked as a StateObject. Changes in the data from ViewModel are published via property which is marked with published property wrapper and changes are reflected in the UI.

Let’s create view for our DevTechieCourse app:

struct DevTechieCourseView: View {
    @StateObject private var viewModel = DevTechieCourseViewModel()
    
    var body: some View {
        NavigationView {
            List(viewModel.courses) { course in 
                VStack(alignment: .leading) {
                    Text(course.name)
                    Text("\(course.courseLength) mins")
                        .foregroundColor(.secondary)
                }
            }
            .listStyle(.inset)
            .navigationTitle("DevTechie.com")
        }
        .onAppear {
            viewModel.populate()
        }
    }
}

struct DevTechieCourseView_Previews: PreviewProvider { static var previews: some View { DevTechieCourseView() } }
We have only taken a single app view as an example to understand the concept and to keep things simple but this idea can be extrapolated into a much complex app. Hope this helps to understand MVVM design pattern in SwiftUI space.

With that we have reached the end of this article. Thank you once again for reading. Don’t forget to follow 😍. Also subscribe our newsletter at https://www.devtechie.com