š¦āš»Last Stop to learn MVVM in iOS Development
Today marks the end of your confusion about MVVM. By the time you finish this, youāll be equipped to effortlessly write MVVM code on your own.
Before going to practical code, letās take a look at basics of MVVM.
The Model-View-ViewModel (MVVM) is a structural design pattern that guides the software structure and how objects are organized and interact. Itās particularly useful in iOS development to separate the user interface logic from the business logic, improving the modularity and reusability of your code.
Components of MVVM
The MVVM pattern consists of three main components:
Okay, letās see something practical to understand deeply:
Remember: āA Model is a representation of data and business logic that defines the structure and behavior of an applicationās core entities.ā
Here is a model of a Banner in iOS App having like this:
import Foundation
// MARK: - ModelData
struct OurData: Codable {
let data: BannerAd?
enum CodingKeys: String, CodingKey {
case data
}
}
// MARK: - BannerAd
struct BannerAd: Codable, Identifiable {
let id: Double?
let contentURL: String?
let contentThumbnailURL: String?
var thumbnailURL: URL? { URL(string: contentThumbnailURL ?? "") }
let contnetThumbnailProperty: ContnetThumbnailProperty?
let videoID: String?
let contentID, contentType, contentTitle, contentDescription: String?
var favourite: Bool?
enum CodingKeys: String, CodingKey {
case id
case contentURL = "content_url"
case contentThumbnailURL = "content_thumbnail_url"
case contnetThumbnailProperty = "contnet_thumbnail_property"
case videoID = "video_id"
case contentID = "content_id"
case contentType = "content_type"
case contentTitle = "content_title"
case contentDescription = "content_description"
case favourite
}
}
// MARK: - ContnetThumbnailProperty
struct ContnetThumbnailProperty: Codable {
let height, width: String?
}
In the provided code, the Model is represented by the OurData
and BannerAd
structures. These structures define the data to be used in the application. Here is how our banner can look:
Okay, cool. Thatās all what model is, it is basically is like a zen master meditating in the background, silently maintaining the cosmic balance of your data universe, your whole app.
Now, letās move to ViewModel,
āA ViewModel is a design pattern that abstracts the presentation logic from the UI.ā
See this code very calmly and read each comment to know what is happening.
import Foundation
// First we will make a protocol `SharableProductVMRepresentable` that our ViewModel will follow
// This is if you want to add some specific functions or you can even add more protocols of
// your own in addition to ObservableObject
protocol SharableProductVMRepresentable: ObservableObject {
var product: BannerAd { get set }
}
// Here i have added all the variables that i'll use one of my specific view
extension SharableProductVMRepresentable {
var thumbnailURL: URL? { product.thumbnailURL ?? URL(string: "") }
var productDescription: String { product.contentDescription ?? ""}
var productContentType: String { product.contentType ?? "1" }
}
// This is our ViewModel
class SharableProductViewModel: SharableProductVMRepresentable {
@Published var product: BannerAd
func anyFunction() { } // You can add functions on data for Views
init(product: BannerAd){ // On call, we will initialise our variable `product` in protocol
self.product = product
}
}
Cool, now you have added all functions you want on that data, and that you want according to user interaction. Now, letās go to and populate our View with data using this ViewModel.
Getting into what is View, as stated earlier āA View is responsible for displaying the visual elements of the app.ā
import SwiftUI
struct ContentView<ViewModel: SharableProductVMRepresentable>: View {
@StateObject var viewModel: ViewModel
var body: some View {
VStack {
if let url = viewModel.thumbnailURL { // We are using `thumbnailURL` in our view
AsyncImage(url: url) { image in
image.resizable()
} placeholder: {
ProgressView()
}
}
Text(viewModel.productDescription) // Using `productDescription` in our view
.font(.body)
.padding()
Text(viewModel.productContentType) // Using `productContentType` in our view
.font(.footnote)
.foregroundColor(.gray)
}
}
}
I want to explain the first two lines seriously, so here, ContentView
is a generic struct that conforms to the View
protocol. It has a generic parameter ViewModel
which must conform to SharableProductVMRepresentable
. This means that ContentView
can work with any type that conforms to SharableProductVMRepresentable
.
@StateObject
is a property wrapper that's used to create and manage a stateful value, or a source of truth, for a given view. When you use @StateObject
, SwiftUI will ensure that the same instance of ViewModel
is used to render this view across multiple render passes. This is important because SwiftUI views are structs, which means they are value types and are destroyed and recreated on every render pass. @StateObject
ensures that the state is preserved across these render passes.
Thatās all for MVVMā ,
Yes thatās all you need in a MVVM structure. Please donāt be shy to ask your questions in comment box.
PostCredit Paragraph
Hmmm no we forgot one thing to make our app functional.
Guess what??
Okay, so we also to fetch the data from API, that weāll discuss in next post.š