July 7, 2013
Every once in a while, usually whenever Apple makes significant changes to Xcode or AppKit/UIKit, an old debate flares up in the Mac and iOS development community: is Interface Builder still a good place to implement UI, or should you do everything in code?
When you're first starting out with Mac or iOS development this question seems like a no-brainer. Most of the tutorials you'll see will be IB-centric, and intuitively it seems like it would be much nicer1 to drag buttons and table views out from an object palette, wire them up, set few visual properties, and then sangria on the deck.
That's how I started but I've since become a code-only convert. Looking back I wish that I had started learning Cocoa with a code-only approach. Although Apple sends the message that IB is appropriate for both new developers learning the frameworks and experienced developers who want to pump out UI in the most time-efficient way possible, I actually think that it's not great at either.
First, the time efficiency. I can't argue that dragging a button out of an object palette and wiring it up to an IB outlet is fast, easy, and kind of fun. But how much of real-world UI is actually that simple? When you get to composite, custom views in contained view controllers, custom layer-backed views, on-the-fly swapping of collection view layouts and so on, you're doing most of the heavy lifting in code anyway and IB just gets in your way. The number of times I have to click through a view hierarchy just to select the right thing is almost as annoying as the opaque consequences of accidentally dragging something out of alignment by a few pixels.
So yes, easy to create trivial UI but difficult to create complex UI and painful to maintain and update it over the lifecycle of the app. It is extremely difficult to understand the IB manifestation of someone else's complex UI. And this is even more true when using Auto Layout2: fighting with IB to set the correct constraints is sufficiently difficult, but actually maintaining the correct constraints while making updates or enhancements to a UI can be time consuming and sometimes utterly baffling.
But if I had started learning with a code-only approach, I would have had an easier time of it in a few ways. First, AppKit/UIKit, unlike some other UI frameworks, is really code-efficient3. You can instantiate a button, set its title, disable auto-resizing mask translation and add it as a subview in 4 lines of code. A few more and you've set layout constraints on it. If you've been using UIAppearance you may not have to do any additional UI styling at all.
Sure, you might have 4 or 8 more lines of code than you would have with an IB-based approach, but look at what you've gained:
You've put the button in the right place. Doing everything in code encourages more thoughtful object encapsulation, avoiding a lot of the header-bloat and insufficiently opaque classes you can get from IB if you're not careful.
You've learned how to keep your code DRY4. The desire to keep the UI code to a minimum will probably motivate you to learn UIAppearance and other best-practices just to keep your code to a minimum. And you'll never again have to walk through your NIBs trying to make sure all your controls use the
You can play the Auto Layout mini-game. It's fun and educational.
-- 1. I've thought a lot about why I initially subscribed to this theory and I'll summarize as follows: first, every book and tutorial I'd seen used IB for layout. Second, I used to do a lot of work in Visual Basic, so drag-and-drop layout was comfortable for me and I had positive associations with it. Third, modern non-Apple UI frameworks that offer imperative (code-based rather than visual) layout as an option, like Microsoft's WPF, are a horrendous hacky painful mess. I currently work on a pure-code WPF-based UI and it's not fun. So the assumption is that they must all be this painful, and visual layout would almost certainly be better.
2. Auto Layout is what prompted my switch to code-only UI development.
3. Not everyone agrees with this assessment, and I haven't tried all the different web and native frameworks out there, but it's pretty damn efficient for what I'm used to.
4. Don't Repeat Yourself. The programming principle of not duplicating the same snippet of code, instead centralizing it and calling it from multiple locations as needed. DRY code tends to be less prone to error and easier to maintain and extend. Copy-paste code, on the other hand, tends to be a maintenance nightmare.