How to create an IBInspectable of type enum How to create an IBInspectable of type enum xcode xcode

How to create an IBInspectable of type enum


Swift 3

@IBInspectable var shape:StatusShape = .Rectangle merely creates a blank entry in Interface Builder:

Not available in IB

Use an adapter, which will acts as a bridge between Swift and Interface Builder.
shapeAdapter is inspectable from IB:

   // IB: use the adapter   @IBInspectable var shapeAdapter:Int {        get {            return self.shape.rawValue        }        set( shapeIndex) {            self.shape = StatusShape(rawValue: shapeIndex) ?? .Rectangle        }    }

Available in IB

Unlike the conditional compilation approach (using #if TARGET_INTERFACE_BUILDER), the type of the shape variable does not change with the target, potentially requiring further source code changes to cope with the shape:NSInteger vs. shape:StatusShape variations:

   // Programmatically: use the enum   var shape:StatusShape = .Rectangle

Complete code

@IBDesignableclass ViewController: UIViewController {    enum StatusShape:Int {        case Rectangle        case Triangle        case Circle    }    // Programmatically: use the enum    var shape:StatusShape = .Rectangle    // IB: use the adapter    @IBInspectable var shapeAdapter:Int {        get {            return self.shape.rawValue        }        set( shapeIndex) {            self.shape = StatusShape(rawValue: shapeIndex) ?? .Rectangle        }    }}

► Find this solution on GitHub.


Instead of setting your inspectable enums with ints, you could also set them with strings. Although not quite as preferable as a dropdown, at least this option offers some level of readability.

Swift-only Option:

// 1. Set up your enumenum Shape: String {    case Rectangle = "rectangle" // lowercase to make it case-insensitive    case Triangle = "triangle"    case Circle = "circle"}// 2. Then set up a stored property, which will be for use in codevar shape = Shape.Rectangle // default shape// 3. And another stored property which will only be accessible in IB (because the "unavailable" attribute prevents its use in code)@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'shape' instead.")@IBInspectable var shapeName: String? {    willSet {        // Ensure user enters a valid shape while making it lowercase.        // Ignore input if not valid.        if let newShape = Shape(rawValue: newValue?.lowercased() ?? "") {            shape = newShape        }    }}

It is possible to also get this to work with objective-c as well, by adding an initializer to the enum. However, the compiler will only show the "unavailable" error for your IB-only properties in swift code.

Swift Option with Obj-C Compatibility:

@objc enum Shape: Int {    case None    case Rectangle    case Triangle    case Circle    init(named shapeName: String) {        switch shapeName.lowercased() {        case "rectangle": self = .Rectangle        case "triangle": self = .Triangle        case "circle": self = .Circle        default: self = .None        }    }}var shape = Shape.Rectangle // default shape@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'shape' instead.")@IBInspectable var shapeName: String? {    willSet {        if let newShape = Shape(rawValue: newValue?.lowercased() ?? "") {            shape = newShape        }    }}


I can't remember the swift syntax, but this is how I solved it in obj-c

#if TARGET_INTERFACE_BUILDER@property (nonatomic) IBInspectable NSInteger shape;#else@property (nonatomic) StatusShape shape;#endif