A little disclaimer before starting

I’ve been working as a React Native and iOS developer for a few years now. iOS has always fascinated me because of the ecosystem and the community behind it. The same reason I am attracted towards React Native. I feel it's the community that we are ultimately building for.

SwiftUI came in a good time for me. I saw a nice Dribbble shot with the app concept to calculate the budgets of future plans like trips, shopping, etc. I decided to implement it with SwiftUI to test what SwiftUI has to offer.

Xcode 11 beta 5

This design concept was made public by Juan Fer on Uplabs. So big shoutout to him, we surely need more designers like him. Here are the few takeaways from building it in SwiftUI.

My first impression of SwiftUI is that it promotes a minimalist approach to problem-solving. Everything can be divided into small manageable chunks. There is an aura of simplicity you feel while working with it. I naturally wanted to keep everything within a single file. I found you can do a lot with very less code and I was able to build something substantial in less than a week using a single file. This speaks a lot about SwiftUI as a framework. It is great for prototyping and iterating over ideas quickly.

However, the honeymoon period ended eventually and the shortcomings started to show up. What kept me going was the project that I was building. Like any other relation, you have to be persistent and always look at the bright side when things don’t work out. That is when I decided to take a deeper breath and extracted the views into their own files as it is better for readability especially when the project grows and more developers join the ranks.

For organizing the project, I went with what I felt right and structured the code in a way that came naturally to me instead of following any specific pattern. I feel that everyone should innovate until a consensus is found in doing something new.

Structure

I found there are three kinds of different views that I mainly used.

> View builders
> View groups
> View molecules

> View builders
View builders are components that take different views as an argument and return a new component adding more functionality to the resulting view. For this project, I created a custom segue component that took two views and displays the second one as a segue based on a boolean.

> View groups
As the name suggests, this is where two or more “view molecules” are grouped together usually in a vertical stack. This is a good place to define the state logic that the molecules share. View groups are mostly used for readability and separating concerns.

> View molecules
View molecules are much like the building block for the UI. They combine multiple default views and have a single purpose. A good example is a ListItemView which combines multiple text and image component wrapped in a horizontal stack. This is also a good place to add animations to the view. A good practice to add animation is at the deepest view level as animation modifier is applied to all children views inside an animated container.

I felt no need to extract the atomic views, like text or buttons, into their own files because they are pretty simple to rewrite and are frequently different from each other when reimplemented.

State and data flow

I won't go in detail about the State and Bindings, however, I found it is better to have a state property as a private variable used in a concentrated scope. If there is a shared state between multiple views across or down the hierarchy I preferred to use the global state, even for the UI.

To share state between multiple views, as seen in the official examples, I used the environmentObject at the rootView level of the project. To define the state I used a separate Model file. A model file is basically an object defined as a class which extends ObservableObject. The published properties can be listened to and modified from anywhere in the app.

Animations

One of the reasons I took on this project was the animations. The concept had unique animations which looked complex at a glance, however, SwiftUI took care of a lot of it.

In essence, you can use the animations either explicitly or implicitly based on your use-case. The explicit animation is defined using withAnimation() decorator and every property updated inside this decorator will be animated. Much like UIView.animate(). The other way, which is the implicit way is even more simple because you can implicitly use the .animation() modifier just like any other view modifier and all the view updates will be animated for you.

I found both of these approaches to be simple to use and you can add any kind of animation to the views with very less effort. Not to mention you can also extract the animations and the animated properties into separate modules as view modifiers which is a nice way to separate the concerns and write cleaner code.

Final thoughts

Overall the experience with SwiftUI was great. However, you have to try it yourself to know what it has to offer. For me I found it almost too fast to work with, easy to iterate and very approachable. The animations are a breeze to add. More importantly, I can dropdown to UIKit whenever you feel like it.

Someone asked me how often did I had to use UIKit? And is there a reason I structured the project the way I did?

To answer that, I believe using UIKit along with SwiftUI is how the new iOS projects are going to be structured. SwiftUI is not replacing UIKit. Consider it is as a new way of structuring the projects. Even if you’re using UIKit with SwiftUI you get all the benefits SwiftUI has to offer. For me, SwiftUI is ready to be released (apart from some minor bug fixings). Because there are just too many lower-level API’s to list that won't be available in SwiftUI at least in the near future and it's pretty clear that they don't have to be.

For example, in this project, I used UIKits ScrollView to scroll the main list to the bottom when a new item is added. This is not possible with the default ScrollView in SwiftUI yet because there is no proper or obvious way to set the content offset. If I set the literal offset of the contained view the list scrolling gets buggy and doesn’t scroll to the top. The easiest way for me to fix this was to dropdown to UIKit. Maybe there is a better way to do this with SwiftUI but the point is that shortcomings of SwiftUI didn’t stop me from making progress and I think that speaks volumes.

SwiftUI is still in beta though so obviously there is a lot more room to improve. Having said that, you should definitely try it if you want to!

This post was originally written for Medium and is re-printed here for archival purposes.