FunctionalTableData and Interface Builder 🎨✨

Interface Builder is amazing for building UI. Code is great for extensibility. Why not use both?

Raul Riera
4 min readMay 5, 2019

I have a long-running joke in my Twitter bio about fighting in the great Storyboards vs Code wars. Using things like Storyboards is a hot topic among iOS developers. There have been many before it:

  • Automatic Reference Counting vs Manual Memory Management.
  • Auto Layout vs Manual Layout.
  • Swift vs Objective-C.

You get the idea, status-quo versus new. I like storyboards, they allow me to create complex views very fast. But, using them comes at a great “merge conflict” cost if you are working with more than yourself.

What can we do about it?

I have praised FunctionalTableData before, a declarative UI building library developed at Shopify. Newcomers to this library will find how verbose it is to create a Cell (UIView subclass, and a State) when compared with similar solutions like React Components.

We can do better by using code for the states, and making the views using Interface Builder. The best of the two worlds.

Putting this crazy idea into practice

We won’t cover how to use FunctionalTableData, we did that in Building Apps with FunctionalTableData. We are going to skip forward and focus on the views. For that, we are going to turn to Xcode’s Interface Builder and create a new .xib file.

Using everyone’s favourite app as a guideline, lets recreate Instagram’s profile header. At the moment of this writing it looks like:

Profile header from Instagram (Image 1)

Turning to Interface Builder, we are going to add UIStackViews, UILabels, UIImageView, and an UIButton. After dragging around a bunch of views, it looks like so:

Finished version of our own Instagram header view (Image 2)

Imagine doing all those stack views and views by code, I am screaming too. But, how do we get this view to work with our HostCell implementation?

Loading the main view from a .xib file

Even though we created everything using Interface Builder, we still need to write a bit of code for our header file. Every IBOutlet connecting the views that we will manage with the state, which we will build later.

Our view (Image 3)

Everything in here looks very similar many apps we have done before, but what is that loadNib method? Without it, we will have to load the UINib from a Bundle, instantiate the view, and then apply constraints to pin it to the edges. Or, we can write a simple protocol to do all of that for us:

Protocol (Image 4)

This protocol is very straightforward, the best thing it does is matching the name of the current class to our .xib file. That way, if we use it in our InstagramHeaderView.swift (See Image 3), we need its corresponding .xib file to be named InstagramHeaderView.xib.

No Cell in FunctionalTableData is complete without a state, let’s quickly create it using the knowledge we already have. If we have previously gone over the trouble of creating small state files for the base iOS views (UIButton, UILabel, etc) using them for big states like this one become as simple as creating properties.

State (Image 5)

Noticed how instead of creating multiple properties to manage everything about a Button or an Image, we simply create a property that holds a ButtonState and an ImageState. To learn more about these states, take a look at FunctionalTableData’s example project.

Putting it all together

You know the drill by now, we normally create a typealias to hide all the implementation details required by HostCell. Our new cell would be something like this

typealias InstagramHeaderCell = HostCell<InstagramHeaderView, InstagramHeaderState, LayoutMarginsTableItemLayout>

That is pretty much it! ✨. Using this cell is something we have cover before, if you need a refresher please head over to Building Apps with FunctionalTableData.

Did I miss anything? Get in touch on Twitter at @raulriera

--

--

Raul Riera

Software Engineer, I make things so you don’t have to. More at https://raulriera.com