[Swift] Using Generics to simplify subclassing UIViewController’s view

Code in Swift
2 min readMar 11, 2022

Before we start with the topic of this article, I’d like to add a little sidenote. For some reason, I see a lot of people creating and storing their subviews in UIViewControllers and not in their UIViews. In thousands of codebases, even in Apple’s sample code, you can see something like this:

This doesn’t feel right. UIViewController should control its views, not create or layout them. But how do you subclass the view of a UIViewController?

What many people don’t realise is that you can easily override the default UIView of a UIViewController with your own. All you need to do is assign it in loadView(). Make sure not to call super in your implementation in accordance to Apple’s documentation.

Our current approach presents us with a problem. Our view’s frame is .zero. The iOS will set a proper size for our view but much later. Later than viewDidLoad() is called. This might cause problems with auto layout and any calculations involving the view’s size.

So we need to set the frame of our view in loadView() method. But how do we know what values to use? The short answer is: we don’t. Unfortunately the logic of the frame’s calculations is hidden behind a private Apple’s API and we can’t access it. What we can do is use our best guess. And our best guess here is UIScreen’s bounds. This is a good default value and in most cases should be equal to the final one.

The other problem is the access to ProductsListView properties is a little awkward. You need to cast the base UIView to ProductsListView first and do it in every call every time.

This isn’t what we want. But it’s an easy problem to solve. Just declare our UIView as a property on the view controller and assign it to the base view later.

Now you can call it directly and we’re finally ready to move to the topic of this article.

What we’ve achieved is already good. We moved a lot of logic from UIViewController to UIView. What we probably want to do next is to make this solution generic, so we don’t have to call loadView() and declare the ui property manually all the time.

We can achieve this by creating a generic UIViewController subclass that would accept a UIView subclass as part of its declaration.

And now our ProductsListViewController becomes as simple as possible.

If you liked this article please retweet it on Twitter or share it in any other social network. It helps more than you think!

--

--