MVC in SwiftUI

This is how MVC looks in SwiftUI, if you do it right

How do you add two numbers?

return a + b

Nah, it’s not OOP enough.

class Adder {    var a = 0    var b = 0    init(_ a: Int, _ b: Int) {
self.a = a
self.b = b
}
func add() { return a + b }
}

Better, but you’d have massive view controller problem. MVVM is the way.

class AdderViewModel: ObservableObject {    var a = 0    var b = 0    init(_ a: Int, _ b: Int) {
self.a = a
self.b = b
}
func add() -> Int { return a + b }}struct Model: View { @ObservedObject var vm = AdderViewModel(...)
}

Good. Now it’s testable, reusable, clean. If MVVM were any smarter it would write itself.

What a load of shit

MVVM is the plague in iOS development.

This article is a top search result in which it states that MVC no longer exists in SwiftUI. Think about this. Control is controlled by view model.

This piece claims MVVM is the new standard architecture.

They are both wrong.

SwiftUI enhances MVC. Now you have automatic model-view binding, so you write less code to manage view updates.

In a sense the best part of MVVM is already built-in. So if anything there are now fewer incentives for you to use MVVM. Why another layer of MVVM on top of MVVM?

Funny thing is that this model-view mapping should be apparent to MVVM developers. This is literally what they’ve been doing all day. Just as they failed to notice that Swift does not have binding before SwiftUI and Combine. For those who did notice, they introduced RxSwift (which is based on KVO)to make things worse.

Most of the MVVM developers I know don’t bother thinking about architecture or improving coding skill. They slapped “ViewModel” to every class name and voila, mission accomplished.

You can write cleaner codes with plain MVC to replace those in above linked articles. I have another article dedicated for that so I won’t cover it here. However I would highlight some common problems among MVVM-ers.

You don’t use MVVM to do networking

You use networking to do networking.

It’s called de-coupling. Just because some mutable property can be used to update view does not mean you should always bundle them altogether.

Let model be model, let view be view. SwiftUI provides way to update view upon model change, use it. As I said, SwiftUI enhances MVC, not replaces it.

For example, you want to retrieve a list from remote site and display it.

Wrap your list in a dedicated networking operation handler reference type which is reusable instead of some bullshit view model that handle network operation implicitly anyway.

Let this handler conform to ObservableObject and publish that list. Observe it in your model. Done. Why do I need view model again?

@State and value type

Instead of putting state/control properties in view model, then observe them, declare them using @State attribute.

Putting state properties in view model makes view model take the role of control implicitly. And when there are multiple view models, you risk contention and conflict of control.

These are the things that MVVM won’t tell you. The only thing MVVM-er would tell you is that you are risking massive view controller. Here, take this even more massive and messy view model to prevent it.

Moving stored property out of model does not solve anything. You are just making the access of it more difficult and error-prone.

For example you want to build a chocolate-milk factory. You want chocolate and milk resources as close to your factory as possible. Bring the factory to chocolate or bring milk to factory is just extra work.

To make things worse, there are usually core properties that other properties build upon. Once you move core properties in one place, you have to move all associated there too. All more unnecessary work.

On the other hand, there’s a reason SwiftUI uses value type in model-view mapping, and goes out of its way to implement @State so you can have mutability from within value type. SwiftUI would just create a new model on mutation and rebuild view from which. Other than that, the model is immutable.

In the mean time, MVVM-ers are stuck in the past using reference type view model without any security check on mutation. And this is where you decide to put your state property?

And remember, this is a view model nested in a model that maps to view. All the extra work for what?

Don’t use view model for control

It’s funny how MVVM-ers ignore C in MVC. If your MVC codes are messed up, chances are due to you can’t manage control codes properly. Most of the same problems would still be present in MVVM since view model doesn’t address control in any way.

MVVM-ers like to talk about clean architecture, re-usability, easy-to-test. The fact is that the more you couple things in whatever object you call it, the more difficult it is to do any of which.

Once you put networking in view model, all hell break loose since everything is built around that. View model becomes view controller… which is the very thing MVVM swore to destroy.

The genius of SwiftUI is that it wants you to use value type model for safety while providing out-of-box model-view mapping.

Then it introduces @State so you have explicit control/state properties within a value type which cannot be mutated outside of model scope.

Model, View, Control, all in one value type.

Most MVVM-ers are so used to view model paradigms, they think MVVM is about having a view model object.

Asgard is not a place, it is people.

MVVM is not about having a view model object, it’s about having a model-view binding. And you have it in SwiftUI out-of-box.

What makes you think you need a nested view model object in SwiftUI to do MVVM?

The rise of MVVM?

The fall of Skywalker

All evidence to the contrary.

You didn’t have proper support for MVVM in iOS before, and you don’t need MVVM now.

At this moment Internet is still full of MVVM nonsense. I hope this article can make top search result to help some developers.

MVC. I have spoken. This is the way.

--

--

--

Casual iOS developer

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Continuous Integration vs Continuous Delivery vs Continuous Deployment

My experience so far at the bootcamp

Move It Like You Mean It: Animating Sprites

OD LAB / Arduino Uno / Experiments / Applications

Learning to Code in a “Retro” Programming Environment

How to move Windows 10 to an SSD

CS373 Spring 2022: Kristina Zhou

Documenting PHPStan + Drupal!

PHPStan

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Jim Lai

Jim Lai

Casual iOS developer

More from Medium

Throttling and Debouncing in SwiftUI

Preventing Memory Leaks Using XCTests

Dev Log (Kanji Aid #2)

Managing SwiftUI State Using Redux