4 Things to Consider Before Adopting SwiftUI in a UIKit Project
How DelightRoom's iOS team transitioned to SwiftUI
When SwiftUI was first introduced at WWDC 2019, I eagerly tore into it. But as I looked closer, it felt a bit too early to use in production (honestly, I didn't fully understand it back then...), so I decided to wait.
Since then, SwiftUI has matured a lot, and I had a few chances to chat with teams actually using it in production projects. I shared the trial and error they experienced with my teammates, building up our internal insights.
Through these various insights, we expected that declarative UI development would not only make maintenance easier but also speed up our development time. So, we started seriously considering applying it to our project in Q1 2022.
As I organized the trial and error we went through to actually adopt it in DelightRoom's iOS project,
I found there were four major considerations:
Setting a shared goal
Considering compatibility
Migrating existing UI
Learning curve
#1 Setting a shared goal
Even if someone says "Let's use SwiftUI!", everyone's passion for trying something new can be different.
You might end up with some teammates aggressively adopting SwiftUI, while others do not.
To get everyone on the same page and match their level of enthusiasm for using SwiftUI, you can try setting it as a shared team goal.
In fact, our iOS team included SwiftUI in our quarterly goals.
Since DelightRoom sets goals using quarterly OKRs, we were able to set a more quantitative and clear goal.
As we worked toward achieving that goal, our team established the following principles:
All new UI must be built with SwiftUI
Existing UI will be migrated based on discussions within the iOS team
By setting a specific shared goal and laying down these principles, we actually started seeing visible results.
#2 Considering compatibility
SwiftUI is available on iOS 13 and above. So, I figured once we bumped our min SDK target to 13, we could use it aggressively. However, after tech discussions with teams that had already adopted SwiftUI and some internal debate, we decided we needed to bump it to iOS 14 or higher to use it effectively in production.
In particular, some SwiftUI components weren't usable in iOS 13, and even in iOS 14, certain components weren't available depending on the minor version.
(For example, the LazyVGrid component is only available in iOS 14 and above.)
(Looking back, I thought we could use it pretty smoothly without restrictions once we hit iOS 14.7. But then WWDC 2022 rolled around with iOS 16 introducing a bunch of new components, while the ones we were just getting used to got deprecated... *sigh*.)
Beyond technical compatibility, we also had to make a call regarding our users.
Because DelightRoom builds a user-centric product, we had to consider how many users would miss out on future updates if we bumped our min SDK target to 14.
From a business perspective, we decided to raise the min SDK to 14 once the percentage of users on iOS 13 or lower dropped below 0.5%.
iOS users generally update their OS faster than Android users, but there are still a significant number of global users who don't, so a period of waiting was required. While waiting, we prepared for the technical transition to welcome SwiftUI. For instance, we started ripping out Rx for asynchronous operations and replacing it with Combine and Swift async/await, and we tried to reduce external dependencies by leveraging more native Apple frameworks.
#3 Migrating existing UI
We couldn't migrate all our existing UI to SwiftUI overnight, so I thought having a set of rules for the process would make things clearer. But as we proceeded, exceptions naturally popped up, and we handled those case-by-case through team discussions.
The main considerations we discussed were:
Does the engineer prefer to use it?
Is this a high-impact area?
Is the difficulty level high?
Engineer preference
Depending on the task, we asked the engineers if they wanted to apply SwiftUI and left the decision up to their autonomy.
We couldn't just force everyone to use SwiftUI. After all, there are business goals to hit in any given sprint, and when technical maturity isn't quite there yet, the work can become overwhelming.
Whether it's a high-impact area
Our goal was to minimize the business impact caused by bugs introduced during development,
so for high-impact areas, we tried to make small, iterative improvements.
Task difficulty
For implementations that were difficult not only technically but also in terms of product spec, to minimize bugs,
we tried to break the area down and improve it gradually.
Ultimately, these three considerations served as principles to help engineers confidently build their technical maturity while ensuring that even if mistakes happened, the business impact would be low.
Also, not everything in UIKit has a 1:1 matching SwiftUI Component.
Therefore, there were times we had to mix and match it with UIKit. A specific example is UICollectionView. To get a similar look in SwiftUI, you have options like 1) ScrollView + V/HStack, 2) List, or 3) ScrollView + LazyVGrid. However, to handle all the rich features that UICollectionView provides out of the box, you have to write a lot of additional implementation. (Beyond just features, I think matching UICollectionView's performance requires even more customization.)
Even in WWDC 2022: Use SwiftUI with UIKit, rather than suggesting a direct SwiftUI Component replacement for UICollectionView, they cover how to use it well alongside UICollectionView.
#4 Learning curve
Because SwiftUI introduces concepts that are quite different from traditional UIKit workflows, our team had some learning to do.
Thankfully, we had folks on the team who were already using SwiftUI in their personal projects, so it was a huge blessing that we could freely share their know-how as we applied it to our work.
Still, we needed to raise the baseline level of SwiftUI knowledge across the whole team, so we took time for group study. The iOS team does quarterly workshops, and during one of them, we carved out four hours to go through Apple's SwiftUI Tutorial together. (Apple did an amazing job with this tutorial. The curriculum of concept + hands-on practice + quiz is fantastic.)
The SwiftUI Tutorial is a 4-hour, 25-minute course divided into four main chapters.
It's hard to finish all four chapters in four hours, and we felt we didn't need to learn the last chapter right away, so we skipped it. Instead, we solidified our learning by taking time to discuss any curious points with teammates as we went along.
If there was a killer feature in the tutorial, it was the quizzes. During hands-on practice, you sometimes end up just blindly typing along without truly grasping the concept, but the quizzes were perfect for correcting that. We even discussed internally that they would make great interview assignment questions later on.
Finding the right architecture
When we were using UIKit, we were using a Clean Architecture MVVM approach internally. As we started using SwiftUI, we began to question whether we should just port over our existing architecture. So right now, we are in the middle of trying to adopt TCA.
Conclusion
Try keeping these four things in mind when adopting SwiftUI in an existing project:
Setting a shared goal
Considering compatibility
Migrating existing UI
Learning curve
If you're still hesitating or unsure of how to start, I hope you can reference our trial and error
to adopt it in an even better way. 🔥