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 combining more than 1 interface builder file, the interface builder will display just a rectangle without any content.
Re-usability
- Support a style guide for fonts, but when customizing font properties, developers need to set the exact value of each individually. In the case of fonts, this means setting the font name, font size, and font weight from the interface builder.
- Support a style guide for colors, but when setting a color, developers need to pick from the color wheel or set it with a hex value. This color will not be made available for re-use in other places in the project.
Performance
- Support 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 developers can 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 is to present data. All of them require data for presentation. When initializing a view with Interface Builder, developers 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
. This property must be well-defined to prevent app crashes.
Dynamic Layout
In cases where there is a need to present a View or ViewController with a different layout or color depending on applied data, 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 applied data. 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 enough to allow developers to envision the layout without having to look 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 the code has been implemented, encompassing constraints, view properties, and behaviors.
- Developers can be confident that there will not be any element magically displayed on the screen.
- The code is written in a readable and understandable manner, which allows for a comprehensive review of 100% of the code, including 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
Code review is a critical part of the source code acceptance process for the team. Every project requires multiple code review sign-offs before integrating new code into the production codebase. While Interface Builders may be easier for beginners and useful for quick prototyping, the team primarily works on commercial, medium-large scale, and long-term projects. This means that the code implemented must be revisited, maintained, and/or refactored to implement new features. Therefore, the team has opted to build user interfaces programmatically.