šŸš¦āœ‹šŸ»Last Stop to learn MVVM in iOS Development

Aditya Tyagi
4 min readDec 16, 2023

--

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:

Banner in our App

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.šŸ˜ƒ

--

--

Aditya Tyagi

ChainReaderšŸ“š, Youtuber, ProgrammeršŸ‘ØšŸ»ā€šŸ’», Learning filmmakingšŸŽ„, and lifetime Travellerāœˆļø... {GitHub: adityagi02}