Aleksa Simic
May 30, 2024
•
8 min read
Ever since SwiftUI came out in 2019, it was quite natural for all of the iOS developers who started using it to use it in combination with MVVM architecture.
Apple provided us with property wrappers like StateObject and ObservedObject, so it was quite easy to use them for the view models and drive the SwiftUI view updates as soon as some Published property from the view model changes.
Although there is a pretty big hype about the Model View (MV) architecture right now, and people are saying that in SwiftUI you don’t need a view model component, because SwiftUI already provides that for you, the fact is that all of the biggest apps built in SwiftUI are leveraging MVVM architecture of some sort.
MV architecture or simply no view models in SwiftUI can work, but for small projects, as soon as the app starts to scale and unit testing and maintainability become more important, MV and no view model approaches easily fall behind the MVVM.
In my first ever SwiftUI app I had a chance to work on, one of the biggest forecast mobile apps in Switzerland, we managed to successfully migrate the whole codebase, which was pretty big, to SwiftUI completely by using it with MVVM architecture. To get more understanding of how big of a project it was, I will share with you that the app was initially written in Objective-C, then, at some point, completely rewritten in UIKit, and finally, when I came to the project, completely rewritten in SwiftUI.
Most of the issues we had back then in 2021. when this migration happened was not about MVVM at all, they were about SwiftUI. Because, at that point, when we could support only iOS 13.0, in which the initial SwiftUI release happened, we couldn’t use all of the fixes and improvements Apple introduced to SwiftUI in the meantime. Anyway, we managed to get around them by doing some “hacky” fixes or just using UIKit for those components.
Also, we were able to properly unit test the entire codebase because in MVVM we could easily inject mock services in the view models and unit test them. Because of that, after we released the SwiftUI version of the app to the clients, we only had around 20 bugs in total.
After that, in my digital agency, I had a chance to work on around 10 different iOS apps for our clients and we successfully delivered them using SwiftUI and MVVM. Some of them were smaller, while some of them were pretty big-scale, and we didn’t experience any issues with MVVM on any of those projects.
To conclude, I want to share one more MVVM success story. So I am actively working at the moment on one large-scale iOS app that is used by millions of people around the world. And guess what? It’s using MVVM. To be honest, it is combining MVVM with Clean architectures and modularization, both vertical and horizontal, but MVVM is the core of everything happening in the app.
Many large scale companies like Adidas, Crypto.com and The Browser Company are already using TCA in their production iOS apps.
At some point 4 years ago, while SwiftUI was still in its real stages, people in the iOS community started talking about how it would go much better with some Redux-like architecture with SwiftUI being a declarative framework. At that point, the guys from PointFree created just what the community wanted, Redux-like architecture called The Composable Architecture (TCA).
When I first saw it, I immediately wanted to give it a try. At that point, we were about to start the work on one iOS project for which I knew that it would be a large-scale one. I decided to go with TCA on that one.
So we started going through all of the available TCA courses online and implementing that on the real project in parallel. After 1 year of actively working with TCA on that project, these were our impressions about the architecture and how it works with SwiftUI:
Pros:
Cons:
When we started working on the app using TCA, we started slowly, but once got over the learning curve and got to speed, we started delivering features pretty fast and everyone was pretty happy about it.
But as the app scaled, problems started occurring. Eventually, after some time, we decided to slowly start refactoring views that are using TCA to the good old MVVM + Clean + Modularized architecture. A couple of days ago, I came across a post where Rod Schmidt is talking about his 3-year working experience with TCA: https://rodschmidt.com/posts/composable-architecture-experience/. Even though we have been working with it around for about 1.5 years, our experience is pretty much the same so I would like to share some things Rod is talking about in his post and compare them to our experience:
Those were the main reasons we decided to slowly fall back from the TCA to MVVM + Clean + Modularized architecture at some point. Initially, I wasn’t sure if that was a good idea because I was aware of just how powerful TCA architecture is. But after I saw that more people are having the same experience as us, I was certain it was the right move, and that it is better we made it now instead of when the app scales further.
While both of these architectures are pretty viable and can be used in large-scale iOS applications, I would recommend people to use TCA only if they have a team of highly skilled iOS developers who could understand everything that is going on under the hood and maximize what the library provides.
On the other hand, if you want to play a safe game, I would recommend you start with MVVM. Then, when the app starts to scale you can go and introduce Clean architecture on top of the MVVM, and then finally, if there is a need, you can introduce vertical and horizontal modularization. I can guarantee you that you will have no problems with scaling your iOS app.
iOS engineers from all over the world found these e-books and project templates as the ultimate source of knowledge needed to build and scale their mobile apps