When I first learned Cocoa, I didn’t get Interface Builder. It seemed like a beginner’s tool that gets in the way of anything more complicated than a tip-calculator. For years I worked on big teams that decided IB was off the table.
Last year I reviewed CodePath’s curriculum, which starts students off with Interface Builder. Since classes are target senior engineers who wanted real-world experience, I considered killing IB and forcing everyone to go programmatic. But I knew I first had to give it an honest try.
Well now I’m an Interface Builder convert. It’s a great fit for most projects, even “at scale.” Not only is it a timesaver, but it’ll lead to fewer bugs than going purely programmatic. The advantages should outweigh most anxieties. While there are situation where it won’t fit, it should be the first tool an iOS developer reaches for, and it’s absolutely critical to master.
Auto Layout is a powerful tool for dealing with device fragmentation, localization, and really anything with dynamic layout. However, for complex layouts, it’s hard to juggle all of a screen’s constraints in your head. With size classes in iOS 8, it’s only going to get worse.
If there’s one thing that’s tipped the scales toward Interface Builder, it’s real time feedback for Auto Layout. When you make mistakes programmatically, runtime errors are cryptic, and it’s frustrating to constantly re-running code in the simulator to test fixes. In IB, they’re actually highlighted. It’s a debugger for views.
Static Table Views
Every app has a setting screen. They all have some labels and text fields and switches, and they’re all powered by the same boilerplate code. You could waste an afternoon writing it code, slipping in some off-by-one errors. Or you could offload it to a library you wrote yourself, which you now have to maintain. Maybe there’s a third party library, but you’re back in the same position of offloading code to someone else. Why not give it to Apple, where it’s more battle tested?
While Apple has always Interface Builder, they’ve provided programmatic alternatives on equal footing. Things started to change in Xcode 6, when all new project templates used Storyboards.
Now, WatchKit apps require Storyboards. You cannot configure your UI programmatically.
The Trade Offs
It’s valid to have anxiety over Interface Builder, but I think it’s overblown.
My favorite part of teaching senior engineers from other platforms is getting a fresh perspective on problems. I asked them to play devil’s advocate after trying IB for a weeks.
“It Feels Magical.”
If you’ve used a “magical” framework on a successful project, you’ve been bit. Maybe the project changes direction, or you’ve been successful enough that scaling becomes an issue. In reality, you didn’t save time. You just delayed solving the problem.
While Interface Builder looks magical, it’s pretty simple. Anything you can do in IB, you can map 1:1 to code, and it’s straightforward to follow what IB files do. The Cappuccino team actually built a tool that convert XIBs for use with their web framework.
“What about performance?”
Performance can mean a few things. Memory?
The memory usage between methods should be nearly identical. There is a temporary memory usage increase for using nibs or storyboards, but it is likely very minor compared to the views themselves. Similarly while loading and parsing a file is not free, in many cases the cost of doing so is minor, and has absolutely no effect on the performance of the final generated UI.
– RinceWind, Apple Developer, on the Developer Forms
Performance could mean CPU Time, and Matt Gallagher benchmarked it. Out of the box, IB up to 17% faster than programmatic layout. After some tuning of the programmatic code, it was 5-10% faster. In his conclusions, he said:
Don’t assume that NIB files are always slower than generating views in code — it is not always true. While in general, generating user interface views in code appears to be 5-10% faster than loading from a NIB, the reality is that this difference is small enough that it doesn’t matter and there are certainly some views that load faster from a NIB than from code.
His deliberately contrived setup has a 1.8 second load time, and the difference was only about 100 milliseconds. It was also written in 2010. In real world apps on modern hardware, the difference will be negligible.
On top of this, consider that tableview cells are recycled. So even if it costs a few milliseconds, it’s paid when the screen loads. It should not impact scrolling performance.
Given the low risk, and how little it costs to implement, don’t worry about performance until you’ve benchmarked it in your own app.
“How will it scale?”
If you cram everything into Main.storyboard, you’re doing things wrong. It’s no different than if you try to fit all of your app inside one class in one file. Just like code, you refactor IB files.
As your app grows, split out flows into their own .storyboard files. Then load them programmatically.
let nav = UIStoryboard(name:"SignupFlow", bundle:nil).instantiateInitialViewController as! UINavigationController
When a single flow gets too complex, you can break things down until a storyboard contains a single screen. When that gets too big, generate the controller programmatically and load individual views via XIBs.
“What about merge conflicts?”
As we refactor our Storyboards into smaller IB files, we reduce the risk of conflicts. That said, there’s still a risk, and yes, hand-merging these formats carries risk.
As iOS developers, we have to contend with a much more dangerous file: Xcode projects. Most teams just deal with it. Big companies like Google worry about scaling it, so they built Generate Your Project, which generates IDE project files as part of a larger build process, taking its management out of the hand of the developers. It’s great for Google, but overkill for 99% of apps.
Beyond all that, we already deal with large opaque binaries in our apps: image assets. We don’t draw all our assets programmatically in the name of purity.
You may cringe with that comparison. “Image assets are a designer’s problem!” I wonder if layout should be, too.
Early video games were entirely developed through code. Today, game developers invest in level editors so artists can focus on the work. Today, many iOS teams expect designers to hand engineers an annotated PSD, and the engineer to transcribe it to code. So long as you clearly define boundaries, it seems better to let an artist build out the art and let the engineer focus on integration.
Obviously there apps where IB is the wrong tool for the job. I just think they’re in the minority.
Before you judge IB, ship a real project with it. Once you get past the learning curve, the productivity gains far outweigh the risks.