Skip to content

Study the MVVM-C architecture pattern by creating an example app with SwiftUI.

Notifications You must be signed in to change notification settings

DeokHo98/SwiftUI-MVVM-C-Examples-PokedexApp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

50 Commits
 
 
 
 
 
 

Repository files navigation

SwiftUI MVVM-C Examples PokedexApp

When developing an app with SwiftUI, there are many architecture options to choose from.
Here, we will examine an example using MVVM-C.

Getting Started

  • The app is a very simple example with three main features: a basic list, a filtering function for the list, and navigation to a detail screen.
  • The code was written as first-party as much as possible.
  • Test code is also included.
  • Originally, MVVM includes network communication logic within the ViewModel. However, many programmers separate this logic into components named Repository or Service.
    This example app also follows this approach and separates it under the name 'Network Service.'
  • If you want to focus on the architecture, please pay attention to the PokemonModule.
  • architecture pattern may not be perfect and is not the definitive answer. I am a junior iOS developer with only two years of experience.
  • Feel free to open an issue if there's something missing or you'd like to discuss further.

Example App Photo

Simulator Screenshot - Clone 1 of iPhone 15 Pro - 2024-09-10 at 16 34 19

MVVM-C (Model-View-ViewModel-Coordinator) OverView

MVVM architecture has likely been the most popular since the UIKit days
and is commonly used in apps of moderate size.

The MVVM-C architecture extends the MVVM architecture, which consists of
Model-View-ViewModel, by introducing a Coordinator object responsible for
screen navigation, thus separating the responsibilities that were previously
handled by the View.

Let's take a look at what components there are.

Model

Simply put, the Model represents the data.
It can be data received from external sources (e.g., data parsed from JSON received from a server)
or data created and stored within the app itself (e.g., data from CoreData).

View

The View is responsible for drawing the interface.
In UIKit, it also handled tasks like Delegate processing.
However, in SwiftUI, these responsibilities have been removed, allowing the View to focus more solely on rendering the interface.
Originally, the View was also responsible for screen navigation, but in this architecture, it is handled by the Coordinator, which will be discussed later.
Additionally, the View passes user events to an object called ViewModel, which will be discussed later, and it also displays the data provided by the ViewModel on the screen.

ViewModel

The roles of the ViewModel are as follows

  • Process the data from the Model to prepare it for the View, meaning transforming it into data that will be displayed on the screen.
  • Receive events from the View and perform the necessary actions.
  • Execute business logic.
  • Pass screen navigation events to the Coordinator.

It is the object that performs the above roles.

Coordinator

The Coordinator is responsible for managing screen navigation.
In traditional MVVM, this role was entirely handled by the View. However, if complex navigation logic is kept in the View, the code can become complicated and maintenance can be challenging.
Additionally, it becomes difficult to test. To address these drawbacks, the Coordinator is a separate object designed specifically for this purpose.

Advantages of MVVM-C

By adopting MVVM-C, developers can create more modular, testable, and maintainable iOS applications, particularly beneficial for projects expected to grow in complexity over time.

  • Clear Separation of Concerns:
    Each component has a well-defined responsibility, making the codebase more organized and maintainable.
  • Improved Testability:
    ViewModels and Coordinators can be easily unit tested without dependencies on UI components.
  • Scalability:
    As the app grows, new features can be added without significantly impacting existing components.
  • Relatively easy:
    Implementation pattern that is not too difficult, with a low learning curve.

Disadvantage of MVVM-C

While MVVM-C offers many benefits, it's important to consider its potential drawbacks

  • Consistency Challenges:
    Not all programmers employ the same MVVM-C pattern.
    This means that different projects may use different variations of the MVVM-C pattern, resulting in some inconsistency.
  • In larger apps, complexity increases:
    In more complex apps, all logic except for rendering the View or handling screen transitions may be offloaded to the ViewModel, potentially leading to a Massive ViewModel.

MVVM-C Flow Diagram

스크린샷 2024-09-11 오후 3 11 04

UI Rendering of View and Event Sending to ViewModel

The View renders the UI and sends events to the ViewModel.
These events can be a button tap or an onAppear when the screen is displayed.
In the example app, this applies when the screen is shown or when the filter button is pressed.

Receiving Events and Performing Logic in ViewModel

The ViewModel receives events from the View and performs the corresponding logic.
In the example app, this involves making network requests to the Network Service to fetch List data or executing list filtering logic for the filter button.

Network Communication by Network Service

The Network Service handles communication with external servers and converts JSON data into Model objects to be passed to the ViewModel.

Data Processing in ViewModel

The ViewModel processes the Model provided by the Network Service into data suitable for displaying in the View.
The name ViewModel might be derived from this concept: Model for the View = ViewModel.

Screen Updates in View

The ViewModel does not know about the View. Therefore, the View updates the data to be displayed on its own.
This is done using various binding objects in SwiftUI.
In the example app, @Observable was used.

Screen Navigation by Coordinator

If the ViewModel receives an event related to screen navigation, it delegates this to the Coordinator.
The Coordinator then provides the appropriate View to the app to facilitate screen navigation.

Key points in MVVM-C

Responsibility Separation

  • Model is responsible for handling data.
  • The View is only responsible for rendering.
  • Any other logic is handled by the ViewModel.
    Considering the potential bloat of the ViewModel,
    it's possible to create multiple objects like a Coordinator or NetworkService. However, if the ViewModel still becomes too large and maintaining it becomes difficult, it may be necessary to adopt a more advanced architecture such as Clean Architecture or RIBs.

Data Binding

  • The ViewModel does not know about the View and does not instruct it to display data. Instead, the View automatically updates based on the data in the ViewModel.
    Although you can use frameworks like Rx or Combine for this, SwiftUI provides its own tools like @Observable to handle such updates.

Testability

  • In MVVM, since the View and business logic (ViewModel) are separated, the ViewModel can be tested independently without involving any UI code.
    This enhances the maintainability of the app and improves the efficiency of testing.

About

Study the MVVM-C architecture pattern by creating an example app with SwiftUI.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages