MVVM with SwiftUI for Beginners
Model-View-ViewModel (MVVM) has gained significant popularity, particularly in the realm of mobile app development, and its relevance has further increased with the introduction of SwiftUI. This article explores the implementation of MVVM in SwiftUI through a sample post list, highlighting the key components and their roles.
MVVM can be broken down into three main components:
Model: This component represents the underlying data and its structure. Typically, it consists of one or more structs that define the data.
View: The View represents the user interface elements of the application, encompassing buttons, labels, text fields, and other UI components. It also serves as a visual representation of the data presented to users.
ViewModel: Acting as a mediator between the View and the Model, the ViewModel facilitates the exchange of data. It exposes data from the Model to the View and handles user interactions, managing the business logic such as data preparation, sorting, and event handling.
Let's delve into the implementation of MVVM in SwiftUI using a simple List-of-Posts app as an example.
Firstly, the Model needs to be established. In this case, a struct called "Post" is created with three properties that define the content of each post.
struct Post {
var title: String
var body: String
var author: String
}
The ViewModel is then constructed to prepare the post data for presentation in the View. A class named "PostViewModel" is introduced, which incorporates an observable property, "posts," and a function called "getPosts" responsible for fetching the posts. The @Published property wrapper ensures that changes to "posts" trigger updates in the View.
import SwiftUI
import Combine
class PostViewModel: ObservableObject {
@Published var posts: [Post] = []
func getPosts() {
// Assuming you have a network call or some data fetching logic here
// For example, you might use URLSession to fetch data from an API
// Here we'll just simulate fetching data with some dummy posts
let dummyPosts = [
Post(id: 1, title: "First Post", content: "This is the first post."),
Post(id: 2, title: "Second Post", content: "This is the second post."),
Post(id: 3, title: "Third Post", content: "This is the third post.")
]
// Simulate a delay to mimic network call
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.posts = dummyPosts
}
}
}
struct Post: Identifiable {
var id: Int
var title: String
var content: String
}
Lastly, the View is developed using SwiftUI's declarative syntax. The ContentView struct is defined, displaying a list of posts. The view utilizes the PostViewModel to load and provide the posts. The list's elements consist of rows containing the post's title, description, and ID. The onAppear modifier is applied to call the getPosts function when the view appears.
import SwiftUI
struct ContentView: View {
@ObservedObject var viewModel = PostViewModel()
var body: some View {
NavigationView {
List(viewModel.posts) { post in
VStack(alignment: .leading) {
Text(post.title)
.font(.headline)
Text(post.description)
.font(.subheadline)
Text("ID: \(post.id)")
.font(.caption)
}
}
.navigationTitle("Posts")
.onAppear {
viewModel.getPosts()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
With all the MVVM components in place, the preview canvas displays the three posts. The code achieves simplicity and cleanliness, as the View only focuses on defining the UI without dealing with the underlying business logic.
To summarize, MVVM is an effective architectural pattern for building scalable and maintainable applications. SwiftUI simplifies the implementation of MVVM in projects. The sample post list demonstrates how MVVM can be utilized to create a straightforward yet functional application.
That concludes today's article. If you found it helpful, feel free to leave a comment. Don't forget to subscribe to the newsletter for more insightful posts delivered to your inbox. Thank you, and see you in the next post!