Building User Interfaces for iOS
References and Resources
- iOS User Interfaces: Storyboards vs. NIBs vs. Custom Code
- Why We Don’t Use Interface Builder and Storyboards at Instabug
- Why I stopped using storyboards and Interface Builder
- Avoid Storyboards and Interface Builder
Introduction
There are 3 types of user interface design approaches, each with its pros and cons:
-
Interface Builder
-
UINIB
- Each NIB file corresponds to a single view element which can be laid out in the Interface Builder.
- Note that the name
NIB
is derived from the file extension. The file was previously.nib
and is currently.xib
, but the old pronunciation has persisted.
-
Storyboard
- A visual tool for laying out multiple application views and the transitions (segue) between view controllers.
-
UINIB
-
Programmatically
- Without GUI tools, but instead handling programmatically all custom positioning, animation, etc.
Discussion
Interface Builder
Prototyping
One cannot say that Prototyping is Interface Builder’s advantage because when there is more than 1 interface builder file and we want to combine them, the interface builder will display just a rectangle without any content.
Re-usability
- Supports style guide for Font. But when we want to customize these properties, we need to set the exact value of each individually. For Font, we need to set a font-name, font-size, and font-weight from the interface builder.
- Support style guide for Color. But when we want to set a color, we need to pick from the color wheel or set it with a hex value. This color will not made available for re-use in other places in the project.
Performance
- Supports lazy loading but the benefits are minor.
- Opening an Interface Builder file takes time to render its visualization.
Compile-Time Safety
- Performing
segueIdentifier
(raw string) which does not exist will crash an app. - Opening a View or ViewController implemented with Interface Builder with is not connected correctly to a
class
,@IBAction
,@IBOutlet
will crash an app. - Xcode automatically generates
@IBOutlet
with an implicitly unwrappedoptional!
setting its default storage toweak
reference whilestrong
reference is recommended since WWDC2015
Code Review
-
.xib
and.storyboard
are Xcode generated files inXML
format with randomly generatedid
and static magic numbers. Both of them are not readable and reviewable. It’s hard to know what properties are configured by the Interface Builder. - The code of those files changes without any reason. Just opening the files in Xcode can trigger code changes.
Merging
- Interface Builder files are not human-readable, which makes merge conflicts very hard to resolve. It’s not impossible to do, but it’s not something you do with confidence like resolving a merge conflict in code.
- Sometimes, FileMerge cannot resolve the interface builder files conflict.
Data Flow
The purpose of View and ViewControllers are for presenting data. All of them require data for presenting. When initializing a view with Interface Builder, we need to expose each property (or create a setter function) and that property needs to be defined as var
with optional type or implicitly unwrapped optional
instead of private let
. We need this property well otherwise it could crash an app.
Dynamic Layout
Imagine that we have a need to present a View or ViewController with a different layout or color depending on data we apply to. There are two options to make this work: 1. Building another View or ViewController in a different layout for different data. This is not reusable. 2. Implementing a branching condition for the View or ViewController layout depending on the data we apply to it. This can only be done programmatically. As a result, the layout code would now be both in the Interface Builder and application code.
Programmatically
Prototyping
No visualization but the code is readable so we can picture the layout instead of looking at a rendered view.
Re-usability
- Any view implemented programmatically can be designed in a reusable fashion.
- Style guide support.
- Inheritable class.
Performance
No lazy-loading support. As a consequence, all views are initialized right away including subviews. But the performance hit is minor.
Compile-Time Safety
The compiler checks the layout code and ensures that the code is written in such way that a method is only called if the object can be unwrapped. The error is prevented before the app can even be compiled. No crash, all good ✌️
Code Review
- How it looks on the screen is exactly what we implemented with code, encompassing constraints, view properties and behaviors.
- We can be sure that there will not be any element magically displayed on the screen.
- The code is readable and understandable. We can review 100% of the code even constraints.
Merging
When there is more than 1 developer working on the same file, conflicts can arise. But at least. the code is readable and understandable. Therefore conflicts can be resolved easily.
Dynamic Layout
There are also cases in which custom iOS code is the only option for UI design. Dynamic layouts, where view elements are moved around and the flow or layout adjusts significantly based on content, are typical examples.
Conclusion
For us, code review is a major part of the acceptance of source code. Every project requires multiple code review sign-offs before integrating new code into the production codebase. Interface Builders are easier for beginners to get into, and they are great for quick prototyping. But we are working on commercial, medium-large scale and long term projects. Which means that we need to revisit the code we implemented, maintain it and/or refactor it to implement new features. That’s why er have opted to build user interfaces programmatically.