In modern app development, fetching data from an API is a common requirement. One popular architectural pattern for building robust and maintainable apps is MVVM (Model-View-ViewModel). In this blog post, we will explore how to fetch data from an API using SwiftUI and MVVM architecture.
Setting up the Project
To get started, create a new SwiftUI project in Xcode. We will build a simple app that fetches a list of posts from the JSONPlaceholder API and displays them in a list view.
The Model
Let’s begin by defining our data model. In this case, we have a Post
struct with id
, title
, and body
properties. Add the following code to your project:
struct Post: Codable {
let id: Int
let title: String
let body: String
init(id: Int, title: String, body: String) {
self.id = id
self.title = title
self.body = body
}
}
The ViewModel
Next, we need to create a ViewModel that will handle fetching the data from the API and storing it. Create a new Swift file called PostViewModel
and add the following code:
import SwiftUI
class PostViewModel: ObservableObject {
@Published var posts: [Post] = []
func fetchPosts() {
guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else {
return
}
let task = URLSession.shared.dataTask(with: url) { data, _, error in
guard let data = data else {
return
}
do {
let decoder = JSONDecoder()
let decodedPosts = try decoder.decode([Post].self, from: data)
DispatchQueue.main.async {
self.posts = decodedPosts
}
} catch {
print("Error decoding posts: \(error)")
}
}
task.resume()
}
}
The PostViewModel
class contains a @Published
property posts
that will automatically update any associated views when its value changes. The fetchPosts()
method uses URLSession
to make a network request to the API and decode the response into an array of Post
objects.
The View
Now let’s create the view that will display the fetched data. Replace the contents of the ContentView
with the following code:
struct PostView: View {
@ObservedObject var viewModel = PostViewModel()
var body: some View {
NavigationView {
List(viewModel.posts, id: \.id) { post in
VStack(alignment: .leading) {
Text(post.title)
.font(.headline)
Text(post.body)
.font(.subheadline)
.foregroundColor(.gray)
}
}
.navigationBarTitle("Posts")
}
.onAppear {
viewModel.fetchPosts()
}
}
}
struct PostView_Previews: PreviewProvider {
static var previews: some View {
PostView()
}
}
In this code, we create a HomeView
that initializes an instance of PostViewModel
and observes its posts
property using @ObservedObject
. Inside the view, we display the fetched posts in a list. The navigationBarTitle
sets the title of the navigation bar to “Posts”. Finally, in the onAppear
modifier, we call the fetchPosts()
method to fetch the data when the view appears.
Testing the App
Build and run the app in the simulator or on a device. You should see a list of posts fetched from the API displayed in the app’s view. The data will be populated as soon as it is retrieved from the API.
Conclusion
In this blog post, we explored how to fetch data from an API using SwiftUI and MVVM architecture. We created a PostViewModel
to handle the network request and store the fetched data, and a HomeView
to display the data in a list view. By following the MVVM pattern, we achieved separation of concerns and a clear structure for our app. Feel free to expand upon this example by adding more features or customizations to suit your needs.