• Life Without Interface Builder
  • Originally written by Zeplin
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: Ryden Sun
  • Proofreader: Talisk Allenlongbaobao

Life without Interface Builder

Over the past few months, in the macOS version of Zeplin’s app, we’ve started developing some new features without using Interface Builder or Storyboards.

This is a very controversial topic in the iOS/macOS community, and as a team that relied heavily on Interface Builder, we wanted to share some real world examples of why we made the switch. Even though this article starts with macOS, everything I’ve mentioned can be applied to iOS.

Why is that?

After two years of objective-C, Zeplin wrote one of the modules in Swift for the first time in late 2015. Since then, we’ve been using Swfit to develop new features and gradually migrate existing ones. Currently, 75% of macOS apps are written in Swift.

Interestingly, as soon as we started Swift, we started thinking about abandoning Interface Builder.

Too many mutable types

Using Interface Builder in Swift brings in a lot of optional types (optional types in Swift) that are not in the type-safe domain. I’m not just talking about outlets either, if you use Segues in Storyboards, properties in your data model will also become optional. This is where things got out of hand. Your View Controller requires properties to work, and now that they’re optional, you start writing guards all over the place, you start getting confused, thinking about where you can handle them gracefully, where you can simply escape from fatalErrors. This is very error-prone and significantly reduces the readability of the code.

Your View Controller requires properties to work, and now that they’re optionals, you start writing guards everywhere.

… Use operators unless you use Implicitly Unwrapped Optionals (optional)! . This works most of the time and doesn’t cause any problems, but it feels like cheating the Swift platform. Most of us believe that Implicitly Unwrapped Optionals should be used in very few scenarios and should be avoided in Storyboards for routine development.

Design changes

Writing layout code in Objective-C isn’t too bad, but using Swift is much simpler and, most importantly, easier to read. Declaring Auto Layout constraints is easy and pretty, thanks to libraries like Cartography.

// Define the appearance when creating the propertylet editButton: NSButton = {
    let button = NSButton()
    button.bordered = false
    button.setButtonType(.MomentaryChange)
    button.image = NSImage(named: "icEdit")
    button.alternateImage = NSImage(named: "icEditSelected")
    
    returnThe button} ()... Constrain (View, editButton, self) {view, editButton, superview with Cartography declaration Auto Layoutin
    editButton.left == view.right
    editButton.right <= superview.right - View.margin
    editButton.centerY == view.centerY
}
Copy the code

I guess we can divide developers who use Interface Builder into two types: those who only use Auto Layout and Segues, and those who also use it for add-ons. Set colors, fonts, and other visual properties in Interface Builder.

When using Interface Builder, you’ll find yourself copying and pasting your previously written views — and you won’t feel bad about it.

We fall slightly into the second category! Zeplin was a fluid app, and when only the design elements changed, it eventually started to bother us. Let’s say you only need to change the background color of a public button. You need to open each NIB file and change them manually. When this has to be repeated a lot, you might miss something.

When you write views in pure code, this gives you an incentive to reuse the code. On the contrary, with Interface Builder, you’ll find yourself copying and pasting your previously written views — and you won’t feel bad about it.

Reusable views

According to Apple, Storyboards are the future. Since Xcode 8.3, we have not had an option not to use Storyboards when developing projects. 😅 It is really sad that there is no straightforward way to reuse views in Interface Builder.

That’s why we find ourselves writing common views in pure code. Creating a view that can be initialized with both code and NIB is also tricky, forcing you to implement both constructors and do the same initialization behavior. When you’re just using code, you can safely ignore _init, right? (coder: NSCoder) _.

Behind the transformation

After the transformation, we realized that building interfaces with code improved our understanding of UIKit and AppKit components.

We are converting some of the older functionality that was previously implemented with NIB. When we try to preserve the look, we have to learn more about what the different attributes are doing and how they affect the look of a build. Before, they were just choices and check boxes set by Interface Builder by default, and that’s how they worked.

Building interfaces with code improves our understanding of UIKit and AppKit components.

For navigational components, such as UINavigationController, UITabBarController, NSSplitViewController are all possible. This is especially true for novices, who rely heavily on these components without really understanding how they work behind the scenes. When you try to initialize and use them in code, you immediately feel comfortable.

Zo had a hard time opening a huge Storyboard.

Debugging problems

Has there ever been a bug that you spent a few minutes tracking down and discovered was caused by an outlet that wasn’t wired up or an option in the NIB that you accidentally changed?

Every component you create with code is packaged in a separate source file, so you don’t have to worry about jumping between niB and source. This will help us debug problems faster and introduce fewer bugs in the first place.

Code review and merge conflicts

In order to read and understand the NIB, you have to be a NIB wizard, or you have to spend quite a bit of time! That’s why ** most of the time, people just skip niB changes when reviewing code, because it’s too scary. Consider these potential visual bugs that could be eliminated simply by using constants and literals in your code.

Among the objections to NIB, the amalgamation of conflicts is the complaint you will hear most often. If you’ve ever worked on a project that uses NIB, Storyboards in particular, you’ve probably experienced it yourself. You know what this usually means: one’s work needs to be rolled back and reapplied. These are the most annoying conflicts, and they get more and more frustrating as your team gets bigger. You can assign tasks accordingly, which can overcome this problem most of the time. But in Storyboards, this can happen even when you write a separate ViewController.

Surprisingly, this wasn’t a problem for Zepin at the time — we were a small team, I guess. That’s why I saved this for the end.

conclusion

I’ve listed a number of reasons why it’s a good idea to stop using Interface Builder, but don’t get me wrong, there are some use cases where using Interface Builder makes sense. Even if we deliberately omit these use cases, because we are currently much happier without Interface Builder.

Don’t be afraid to do it and see if it fits into your workflow too!


Thanks to our lovely @ygtyurtsever. Let us know what you think, by leaving a comment below! 👋


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.