Olek

At KISS he works as an Android Developer, but he is also an IT student.

2 April 2019

Why we stopped using storyboards?

postMainImage

When Apple announced introduction of storyboards in iOS 5 to all of us it seemed like that kind of feature that changes the entire architecture and process of building an iOS app. We all jumped into it with hopes that creating UI will become more pleasant and less time consuming. Although at the beginning indeed it was, after some time our attitude towards them evolved and finally few months ago we stopped using them completely.

Note: I should also mention that almost all the flaws I will point here also apply to xib files, that are basically storyboards for single ui views.

What could go wrong ?

As usual general idea was great. Storyboard were supposed to help developer visualize entire application flow, connections between individual view controllers and their view hierarchies. As always when new feature is introduced every tutorial and sample available online was only presenting their adventages and before we even properly thought about it, one of us started implementing login/register scene using them. All went smoothly until second developer joined the project.

Although storyboard is just a text file, its syntax and complexity cannot be compared to easily readable xml files used in Android. When differences are small, one can simply copy paste required attributes however in case of bigger ui changes it's almost impossible to visualize the outcome looking only at storyboard text file.

As app growed our storyboard files became larger and larger and we started to notice 2 other irritating drawbacks.

When you start adding segues (connections) between view controllers, storyboard graph starts looking like spaghetti with all the lines traveling under views, crossing one another and finally causing even bigger disorientation then without interface builder at all. For sure you cannot call it a "clean code".

Even with the best hardware, the fact that you see a live preview of entire storyboard scene and each change makes it rerender causes frame drops, lags and developer’s irritation.

Can we do something about it?

What we initially did to solve those issues was splitting bigger storyboard scene files into smaller ones and smaller ones so finally we end up with a concept that single view controller had its own storyboard file. That way we almost managed to overcome the disadvantages mentioned earlier, however we also had to move segues logic back to swift.

Now at that point we thought that we found a proper compromise, a way to squeeze from storyboards only what is good but as you probably suspect we didn’t. In my opinion there is one issue with interface builder files that makes using them impractical.

Again I’m going to make a comparison with Android environment. Let’s say you want to define a color you use throughout entire application. In Android you put it and a seperate xml file and assign a variable to it. Then in a layout file you can relate to that color via that variable. That way when a client wants to change that color, the change involves only redefining that variable and not updating every place the color was used. In that case the color was only an example. Simillar problem with storyboards concern strings, drawables, dimensions and any other external resources. Not to mention the complexity of resource management in case of different locale, screen size or landscape - portrait modes. Every mobile developer should agree that in that field Android by far beats iOS .

What we end up with?

Finally, after spending much time fighting with interface builder and storyboards we decided to abandom them alltogether. But where to put all the code responsible for ui design? Obvious answer is the view controller class, however in complex scenes it’s definition would easly grow to hundreds lines of code and well, we don’t want that. Also the view controller has always some other responsibilities like delegating lifecycle events and notifications to presenters or view models. Our solution was to declare separate class, attached to each view controller, responsible only for creating the view hierarchy and its layout. We called it the view creator.

protocol ViewCreator {

    var parentView: UIView { get }

    init(withParentView parent: UIView)
    // Add subviews to the view when called
    func setupViewHierarchy()

    // Add constraints to the view when called
    func setupConstraints()

    // Setup required properties when called
    func setupProperties()

    // Localize
    func localize()
}

extension ViewCreator {

    // Calls all other setup methods in proper order
    func setupView() {
        setupViewHierarchy()
        setupConstraints()
        setupProperties()
        localize()
    }
}

Every time the controller is created it initializes connected implementation passing it’s view and calling each method in proper order (method names are self explanatory). What we also started putting pressure is ui elements reusability. How to achieve that? Easiest way is to simply subclass each uikit view, style it the way it reflects app design and use that class instead of default UIkit classes.

One more question that may arise is how to create constraints in code so it won’t become even bigger pain then storyboards. Indeed before introducing anchors in iOS 9 answer wasn’t obvious. Apple proposal was way too much verbose. Luckily, there were many great open source libraries like Snapkit or Purelayout simplifying the process. With anchors in our opinion a set of few simple extensions is more then enough and no external librariers are even needed.

extension NSLayoutAnchor {

    @discardableResult
    @objc func equal(
        to other: NSLayoutAnchor,
        constant: CGFloat = 0.0,
        withPriority priority: UILayoutPriority = .required
    ) -> NSLayoutConstraint {
        let newConstraint = constraint(equalTo: other, constant: constant)
        newConstraint.priority = priority
        newConstraint.isActive = true
        return newConstraint
    }
}

Was it worth it?

Without a doubt. Only drawback was getting used to it. Many of us were for some reason really attached to interface builder and resisted moving design to swift. But no one can blame us for that. It was the the way Apple pushed us to follow.

Olek

At KISS he works as an Android Developer, but he is also an IT student. He specialises in intelligent systems, so if you don’t want to hear that your app is stupid, he is your man.