Photo by Charles Deluvio on Unsplash

Building a UIKit user interface programmatically. Tips & suggestions.

Mike Haidan

--

I’ve been building a UI in code for 2 years and I’d like to share my suggestions and tips with you, which I’ve figured out during this period.

1. Use SnapKit instead of NSLayoutconstraint/NSLayoutAnchor.

It’s hard and time-consuming to set up constraints in code, using NSLayoutconstraint-s, then in iOS 9, were announced NSLayoutAnchor-s. What simplifies settings up.

Even if NSLayoutAnchor-s give a really nice API, still, it requires a lot of time to set up all constraints, that is why I suggest to use SnapKit instead.

Let’s compare these both, starting from NSLayoutAnchor:

subView.translatesAutoresizingMaskIntoConstraints = falseNSLayoutConstraint.activate([
subView.topAnchor.constraint(equalTo: view.topAnchor),
subView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
subView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
subView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])

And similar code using SnapKit:

subView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}

There is a significant difference in the amount of the code, easy to set up and understand. That’s why I highly recommend using SnapKit DSL.

2. Use USStackView as frequently as possible.

This one is obvious, but worth mentioning. Even though it’s easy to set up constraints using SnapKit, it’s always better to not use them at all.

And similar result without UIStackView:

Now the setup method is much harder to understand. Compared to UIStackView, where we need to set up only it’s constraints and everything else UIStackView has done for us.

3. Do not build UI in a UIViewController, but create a subview instead.

Even if we use SnapKit or UIStackView, usually we need a lot of code to build an UI and often we do this directly in the body of a UIViewController. Because of the specification of iOS apps, UIViewController may also contain some services/configurations (especially if we use MVC architecture). As result we will get huge UIViewController and, additionally, nightmare merge requests, if more then one developer is working on the same screen (what I had, when one developer was working on UI and I was updating the logic).

Instead of this approach, we can create a custom UIView and override loadView function and set the view in the body of that function:

Our self.view is a CustomView and all UI configuration is now encapsulated inside CustomView. Now our UIViewController-s are much smaller.

4. Use Lazy Stored Properties for a subview and add the subview in the body of lazy var.

It’s not so obvious why we need to use lazy var-s and why it is so important to add a subview in the body of it, instead of doing this in one setup method.

Let me show you in this example, starting from one setup method:

Looks ok, but what if we need to redesign our component and we move the setup of subtitleLabelabove titleLabel? Of course we will get this crash, because we pinned titleLabel to subtitleLabel (see line 27 from previous listing):

You may suggest, simply don’t put subtitleLabel above and it’s valid point :)
But, in the real world, there may be 10–15 different properties, with different configurations, some of them may appear for a specific state and you’ll notice this issue only at runtime. And here comes Lazy Property to help us. Refactor the code using them:

Now if we move subtitleLabel above, everything works, because properties are initialized and added as subview only when they are called explicitly, so when we configure constraints, a subview already will be added to it’s parent.

It is a very basic example, but it also works for much more complex views as well.

5. Setup UI elements in top/bottom manner.

It’s a really bad idea to set up properties of your view in chaotic order. You may understand how it works now, but after months, if some updates are needed, you need to relaunch your app again and again to understand the code.

Instead configure UI from the top to the bottom, so, as you see the components — in the same manner you see the code. Now it’s much easier to understand/read the code and imagine the UI “in mind”.

6. Use SwiftUI Preview.

It’s possible to use preview not only for SwiftUI, but for UIKit as well!

Check out this amazing article for more details.

Hope this article was useful to you.
Thank you for reading ❤️.

Check out my other articles:

How to handle navigation in SwiftUI
Advanced configuration of UITableViewCell-s

--

--