Active Filters: Interface Builder

Interface Builder is awesome. Assembling our interfaces in it can be a great way to work. Sometimes though, we want to create custom views that we draw and manage ourselves in code. It'd be nice if these custom views could work just as well inside Interface Builder as they do in our code. Today we'll look at two awesome features that debuted with Xcode 6 called @IBInspectable and @IBDesignable. Let's dive in:

@IBInspectable var borderWidth: CGFloat = 0 {
  didSet { layer.borderWidth = borderWidth }

When crafting a custom view, we can make a property “inspectable” in Interface Builder by prefixing its definition with @IBInspectable. Now, when we drag an instance of our custom view onto the canvas in Interface Builder we'll be able to change our properties with native controls!

This technique even works with extensions! Tired of not being able to configure things like a UIButton's borders in IB? Let's add a tiny extension to UIButton to make it more inspectable:

extension UIButton {
  @IBInspectable var borderWidth: CGFloat {
    get { return layer.borderWidth }
    set { layer.borderWidth = borderWidth }

This is great so far, but what we really want is to be able to see the effects of our property edits live in the IB canvas. We can prefix any view's definition with @IBDesignable to tell IB to render the view, live, right on the canvas.

class SpeedometerView : UIView {
  var pieChartView: PieChartView

  @IBInspectable var meterColor: UIColor = UIColor.yellowColor() {
    didSet { pieChartView.segmentColor = meterColor }

  // ...

When we combine the two techniques we unlock a much more intuitive (and fast) way to build custom views. We can even implement a special function called prepareForInterfaceBuilder() on our view where we can configure it with example data that will be drawn only when it's rendered in IB.

If anything goes wrong, we can debug our view by setting a breakpoint like normal, then choosing Editor > Debug Selected Views from Xcode's menu.