Stop using MVVM with SwiftUI

karamage@柿本匡章
9 min readApr 4, 2022

--

Declarative UI does not require MVVM

We are now in an era where declarative UI is commonplace in iOS development.

The SwiftUI development experience is wonderful. It’s great.

But I’ve been thinking lately, as is the norm with SwiftUI, when it comes to “let’s develop with MVVM.”
“Are you sure you want to do that?” I wondered.

Digging deeper into my thoughts…

QUESTION :
Was it really a good idea to adopt MVVM for declarative UI in iOS development?

CONCLUSIONS :
“If you’re going to use SwiftUI, don’t adopt MVVM.”

REASONS:
Because We thought that the existence of ViewModel was not necessary in the era of declarative UI.
I have come to the conclusion that this is the case, and I will summarize my thoughts in this article.

ViewModel is bad and wrong with SwiftUI

Have you chosen MVVM for your architecture in the field of iOS development without thinking deeply?

If you find the MVVM pattern in SwiftUI troublesome or not so useful in your implementation, it may be because the MVVM design pattern does not fit the characteristics of SwiftUI.

Until now, iOS application development has often employed the MVVM architecture.
However, with the advent of SwiftUI, a declarative UI, it has become necessary to consider an architecture that suits SwiftUI.

I tweeted the following before.

There was a time when the ViewModel approach was the mainstream in mobile app development with MVVM.
In a world with declarative UI such as SwiftUI, the thinking needs to change. ViewModel was originally introduced for the purpose of Binding the state to the View and reflecting it to Reactive, but since the declarative UI includes that functionality, ViewModel is unnecessary.

The argument that MVVM is unnecessary is often debated abroad.

In Apple’s developer forums and Reddit, you may also see posts saying “Stop adopting MVVM for iOS development (SwiftUI)”.

Stop using MVVM for SwiftUI
https://developer.apple.com/forums/thread/699003

Is MVVM an anti-pattern in SwiftUI?
https://www.reddit.com/r/swift/comments/m60pv7/is_mvvm_an_antipattern_in_swiftui/

Using ViewModel in SwiftUI is an anti-pattern.
“It’s like driving on the ground with wheels attached when you can fly on a hoverboard.”
There is a post called

Why do we choose MVVM?

Recently, I have been using SwiftUI more and more in my iOS development.

I have been pondering the issue of what to do with the architecture in an app using SwiftUI.

When developing mobile apps, for some reason, we tend to choose MVVM as the architecture.

I’m like, “Why?” I wonder why.

Apple has never even used the term MVVM

This is an old tradition in mobile app development.
It started with Google’s advocacy of MVVM in Android development in 2016. (*I only advocated it.)(*Correction, the original origin seems to be Microsoft.)
Originally, the adoption of MVVM began in the field of Android development, but it has since spread to iOS development as a matter of course.

However
Google’s recommended architecture is MVVM.

Currently, the term “MVVM” is missing from Google’s official architecture guide.
The term “ViewModel” remains subtly, but I have not been able to figure out the exact meaning.

https://developer.android.com/jetpack/guide#overview

The following is a tweet from a Jetpack Compose developer at Google.
He clearly states, “ViewModel is not needed for Jetpack Compose. We recommend to remove it”.

https://twitter.com/JimSproch/status/1396855965509554176?s=20&t=ApxuKpIQRTDslPkOLtIvOQ

What is MVVM?

To begin with, MVVM for iOS development was first developed in the days when there was no SwiftUI.
This was used in the days when View and ViewModel values were bound using reactive libraries such as RxSwift.

SwiftUI.View contains ViewModel equivalent functions.

However, SwiftUI’s View originally includes data binding functionality.
In other words, what was done with “UIKit.View + MVVM” can be done with SwiftUI.View alone.

In other words, SwiftUI.
It is possible to reflect Model values directly and reactively in the View.

With declarative UI, ViewModel has lost its reason for existence

In other words, once SwiftUI included the ViewModel data binding functionality, ViewModel lost its reason for existence, and the word “ViewModel” itself became an obscure term.

Since it is not clear what should be done in the ViewModel layer, all the troublesome things tend to be pushed to the ViewModel layer for the time being. Things that should be done in a different layer are often put in the ViewModel layer.

MVVM is an extra complication

If MVVM is adopted in SwiftUI, it becomes complicated because an extra layer called “ViewModel” is sandwiched in between.

The data flow becomes bi-directional, with the View and Model interspersed with an intermediate layer called ViewModel.

We are concerned that this will diverge from the unidirectional data flow shown in the Apple official documentation.

In the declarative UI era, it would be more beneficial to make the data flow unidirectional.
In SwiftUI development, data flow and state management are more important than ever.
To do this, we need to think about where to manage state to make it a Single Source of Truth, and data flow between components by utilizing the Property Wrapper.

Do not write design patterns for the sake of writing design patterns

In other words, “to adopt MVVM on SwiftUI” would be “SwiftUI + MVVM = MVVM on MVVM.”
It’s a “thanks to MVVM, I’m glad I did MVVM” situation.

It is “writing design patterns for the sake of writing design patterns,” and you have lost sight of the purpose.

To avoid “MVVM on MVVM,” it would be simpler to eliminate the ViewModel layer.

MVVM is not used in React/Vue/Flutter

In the field of React/Vue/Flutter, which also uses declarative UI, the architecture of MVVM is not adopted (it is included in declarative UI), and it seems strange to adopt MVVM only in SwiftUI.

I think it’s strange to use MVVM only in SwiftUI, because it is not adopted in the field of “Vue/Flutter” (it is included in declarative UI). I personally feel that it is not a good idea to create a “ViewModel” in Flutter by dragging the “MVVM” in Android development.

Since the term “ViewModel” is used mostly in the mobile area, I sometimes feel that the meaning of the term “ViewModel” is not conveyed when I talk to engineers in other fields.

When I have a React engineer look at my iOS source code, I ask him, “What does this ViewModel mean?

In the React, flux architecture became mainstream, and I wonder if the same trend will come to SwiftUI. (I hear that many places are gradually starting to adopt TCA, a flux-like architecture, in SwiftUI as well.)

What happens when you stop MVVM?

Separation of UI and logic

When you stop MVVM, you may ask yourself, “How do you separate the UI from the logic after the ViewModel is gone?
This is the question that will arise when MVVM is stopped.

The answer is to separate the UI and logic into a Model or a Flux-like Store.

For small to medium scale applications, MV (Model and View) is all you need.

I think it is better not to create a ViewModel to cut out the logic, because the name does not match the responsibilities.

Required Architecture for Declarative UI

With the advent of declarative UI, I think the era of “when it comes to mobile development, MVVM is the only choice” is over, and we have entered an era of confusion.

Currently, there is no de facto standard architecture or best practice for SwiftUI development, and we are waiting for such a standard to appear soon.
(If there already is, it would be great to know)

In the era of declarative UI, what we really want in large-scale app development is MVI (unidirectional data flow), Flux (The Composable Architecture), and Store/Provider patterns.

Since SwiftUI enables MVVM by default, we can say that it is time for an architecture that solves problems at a higher layer.

The problem is, for example,

“How to do component design?”

The other issues include

“a mechanism for separating the state and logic of components from the View,”

“a mechanism for communicating state management between components,”

and “unidirectional data flow”.

The MVVM architecture does not solve the problem of inter-component connectivity or data flow.

To be more specific, React uses Flux (Redux) and Hooks, Flutter uses the Provider pattern and Riverpod, and so on.

In iOS development, too, we need architectures and libraries that solve problems at the upper layer of MVVM brought about by declarative UI.

The solution to the asynchronous and state management problem of “asynchronously fetching data from the server and displaying it on the screen” is not an architectural problem in the first place, but a solution to the problem of asynchronous data fetching and state management.
The GraphQL client data fetch cache library may provide a solution.

Conclusion

Finally, we conclude that

We believe that the existence of ViewModel is not necessary in the era of declarative UI.
I would also like to stop using the term “ViewModel” as a place to cut out logic.

This means “I think this way,” not “This idea is absolutely correct.

I think there are many different code bases, backgrounds, ideas, perspectives, and interpretations of the code base you are looking at, and whether or not the choice is a good one.
(I do, however, take critical comments on this article seriously. I apologize for any anger or misunderstanding caused by my lack of knowledge or explanation.)

In addition, this article will not recommend a particular architecture, saying, “Well, let’s stop MVVM and adopt a 00 architecture.
(I myself have not yet come up with an answer myself ><)

I considered adopting TCA (The Composable Architecture), but I am concerned that it is a bit too grandiose. What should we do?
(Note: After considering this, we have come to the conclusion that TCA is premature.)

The Composable Architecture
https://github.com/pointfreeco/swift-composable-architecture

However, we recommend that you “think carefully” about adopting the right architecture for the application.
Even if the result of your consideration is “Let’s adopt MVVM after all,” that is fine, and I do not intend to reject your idea at all.

My intention is not to disparage MVVM, but rather to say that I think the current trend of “adopting MVVM without thinking” is not a good idea. I have done so.

Thank you for reading to the end.

PS

I thought I may have caused a misunderstanding, so I will add this.

Tweets that I felt were misunderstood:
“ViewModel = ObservableObject.”
“You mean you don’t use ObservableObjects?”
“Does that mean we should only use @State?”

I saw a post that was misunderstood, so I would like to add this.

The SwiftUI’s ObservableObject is the ViewModel itself,” which is both true and different.

Who in the world decided that “ObservableObject is the ViewModel”?

You can think of an ObservableObject as “just” a reactive object and not a ViewModel.

It is natural to think of an ObservableObject as just a Model/StateHolder.

ObservableObject is a part of SwiftUI and should be used more and more.
This article is not intended to say “Stop using ObservableObject.
We hope you understand.

By the way, I would like to point out that the name “ViewModel” is not a good name for the ObservableObject.
I think it would be better to put the Model name/Store name/Domain name/use case name, etc. as it is.
(pull out the ViewModel layer).

Thanks.

--

--

karamage@柿本匡章

Software developer. Mobile apps and Web3. I’ve developed apps that “My Thanks Diary”. I’m good at Flutter, React, Vue. https://github.com/karamage