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
There are 3 types of user interface design approaches, each with its pros and cons:
- Each NIB file corresponds to a single view element which can be laid out in the Interface Builder.
- Note that the name
NIBis derived from the file extension. The file was previously
.niband is currently
.xib, but the old pronunciation has persisted.
- A visual tool for laying out multiple application views and the transitions (segue) between view controllers.
- Without GUI tools, but instead handling programmatically all custom positioning, animation, etc.
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.
- 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.
- Supports lazy loading but the benefits are minor.
- Opening an Interface Builder file takes time to render its visualization.
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
@IBOutletwill crash an app.
- Xcode automatically generates
@IBOutletwith an implicitly unwrapped
optional!setting its default storage to
strongreference is recommended since WWDC2015
.storyboardare Xcode generated files in
XMLformat with randomly generated
idand 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.
- 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.
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.
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.
No visualization but the code is readable so we can picture the layout instead of looking at a rendered view.
- Any view implemented programmatically can be designed in a reusable fashion.
- Style guide support.
- Inheritable class.
No lazy-loading support. As a consequence, all views are initialized right away including subviews. But the performance hit is minor.
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 ✌️
- 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.
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.
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.
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.