如何创建枚举类型的IBInspectable

时间:2021-01-26 16:00:44

enum is not an Interface Builder defined runtime attribute. The following does not show in Interface Builder's Attributes Inspector:

enum不是一个接口构建器定义的运行时属性。接口构建器的属性检查器中没有显示以下内容:

enum StatusShape:Int {
    case Rectangle = 0
    case Triangle = 1
    case Circle = 2
}
@IBInspectable var shape:StatusShape = .Rectangle

From the documentation: You can attach the IBInspectable attribute to any property in a class declaration, class extension, or category for any type that’s supported by the Interface Builder defined runtime attributes: boolean, integer or floating point number, string, localized string, rectangle, point, size, color, range, and nil.

从文档中:您可以将IBInspectable属性附加到类声明、类扩展或类别中的任何属性,这些属性是由接口构建器定义的运行时属性所支持的:布尔、整数或浮点数、字符串、本地化字符串、矩形、点、大小、颜色、范围和nil。

Q: How can I see an enum in Interface Builder's Attributes Inspector?

问:如何在接口构建器的属性检查器中看到枚举?

6 个解决方案

#1


55  

Swift 3

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

@IBInspectable var shape:StatusShape = .矩形只在界面构建器中创建一个空白条目:

如何创建枚举类型的IBInspectable

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

使用适配器,它将充当Swift和接口构建器之间的桥梁。shapeAdapter由IB检查:

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

如何创建枚举类型的IBInspectable

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:

与条件编译方法(使用#if TARGET_INTERFACE_BUILDER)不同,形状变量的类型不会随目标而改变,可能需要进一步的源代码更改来处理形状:NSInteger vs. shape:StatusShape变量:

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

Complete code

@IBDesignable
class 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.

►GitHub上找到这个解决方案。

#2


25  

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.

你也可以用字符串来设置你的检查表,而不是用ints。虽然不如下拉菜单更可取,但至少这个选项提供了一定程度的可读性。

Swift-only Option:

Swift-only选择:

// 1. Set up your enum
enum 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 code
var 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.

通过向enum添加初始化器,也可以让它与objective-c一起工作。但是,编译器只会在swift代码中显示您的ibonly属性的“不可用”错误。

Swift Option with Obj-C Compatibility:

与object - c兼容的Swift选项:

@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
        }
    }
}

#3


20  

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

我不记得快速语法,但这就是我用object -c解决它的方法

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

#4


1  

You can't. If you want it to be available in Interface Builder, make your property one of the supported types. In this case, make it an int and cast it to your enum type in code.

你不能。如果您希望它在接口构建器中可用,请将您的属性设置为受支持的类型之一。在这种情况下,将其设置为int并将其转换为代码中的enum类型。

#5


1  

Swift 3 solution based on SwiftArchitect

基于SwiftArchitect的Swift 3解决方案

enum StatusShape: Int {
    case rectangle, triangle, circle
}
var statusShape: StatusShape = .rectangle
#if TARGET_INTERFACE_BUILDER
@IBInspectable var statusShapeIB: Int {
    get { 
        return statusShape.rawValue 
    }
    set { 
        guard let statusShape = StatusShape(rawValue: newValue) else { return }
        self.statusShape = statusShape
    }
}   //convenience var, enum not inspectable
#endif

#6


1  

This is an old thread but useful. I have adapted my answer to swift 4.0 and Xcode 9.0 - Swift 4 has its own little issues with this problem. I am having an @IBInspectable variable with enum type and Xcode 9.0 is not happy, showing me this "Property cannot be marked @IBInspectable because its type cannot be representing in Objective-c"

这是一条旧线,但很有用。我已经把我的答案改成了swift 4.0和Xcode 9.0——swift 4在这个问题上有自己的小问题。我有一个带有enum类型的@IBInspectable变量,Xcode 9。0不满意,显示这个“属性不能被标记为@IBInspectable,因为它的类型不能在Objective-c中表示”

@Eporediese answers this problem (for swift3) in part; using a property for the storyboard but a straight enum for the rest of the code. Below is a more complete code set that gives you a property to work with in both cases.

@Eporediese部分回答了这个问题(对于swift3);为故事板使用属性,但为其余代码使用直接枚举。下面是一个更完整的代码集,它为您提供了在这两种情况下都可以使用的属性。

enum StatusShape: Int {
  case Rectangle = 0
  case Triangle = 1
  case Circle = 2
}
var _shape:StatusShape = .Rectangle  // this is the backing variable

#if TARGET_INTERFACE_BUILDER
  @IBInspectable var shape: Int {    // using backing variable as a raw int

    get { return _shape.rawValue }
    set {
      if _shape.rawValue != newValue {
        _shape.rawValue = newValue
      }
    }
}
#else
var shape: StatusShape {  // using backing variable as a typed enum
  get { return _shape }
  set {
    if _shape != newValue {
      _shape = newValue
    }
  }
}
#endif

#1


55  

Swift 3

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

@IBInspectable var shape:StatusShape = .矩形只在界面构建器中创建一个空白条目:

如何创建枚举类型的IBInspectable

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

使用适配器,它将充当Swift和接口构建器之间的桥梁。shapeAdapter由IB检查:

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

如何创建枚举类型的IBInspectable

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:

与条件编译方法(使用#if TARGET_INTERFACE_BUILDER)不同,形状变量的类型不会随目标而改变,可能需要进一步的源代码更改来处理形状:NSInteger vs. shape:StatusShape变量:

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

Complete code

@IBDesignable
class 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.

►GitHub上找到这个解决方案。

#2


25  

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.

你也可以用字符串来设置你的检查表,而不是用ints。虽然不如下拉菜单更可取,但至少这个选项提供了一定程度的可读性。

Swift-only Option:

Swift-only选择:

// 1. Set up your enum
enum 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 code
var 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.

通过向enum添加初始化器,也可以让它与objective-c一起工作。但是,编译器只会在swift代码中显示您的ibonly属性的“不可用”错误。

Swift Option with Obj-C Compatibility:

与object - c兼容的Swift选项:

@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
        }
    }
}

#3


20  

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

我不记得快速语法,但这就是我用object -c解决它的方法

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

#4


1  

You can't. If you want it to be available in Interface Builder, make your property one of the supported types. In this case, make it an int and cast it to your enum type in code.

你不能。如果您希望它在接口构建器中可用,请将您的属性设置为受支持的类型之一。在这种情况下,将其设置为int并将其转换为代码中的enum类型。

#5


1  

Swift 3 solution based on SwiftArchitect

基于SwiftArchitect的Swift 3解决方案

enum StatusShape: Int {
    case rectangle, triangle, circle
}
var statusShape: StatusShape = .rectangle
#if TARGET_INTERFACE_BUILDER
@IBInspectable var statusShapeIB: Int {
    get { 
        return statusShape.rawValue 
    }
    set { 
        guard let statusShape = StatusShape(rawValue: newValue) else { return }
        self.statusShape = statusShape
    }
}   //convenience var, enum not inspectable
#endif

#6


1  

This is an old thread but useful. I have adapted my answer to swift 4.0 and Xcode 9.0 - Swift 4 has its own little issues with this problem. I am having an @IBInspectable variable with enum type and Xcode 9.0 is not happy, showing me this "Property cannot be marked @IBInspectable because its type cannot be representing in Objective-c"

这是一条旧线,但很有用。我已经把我的答案改成了swift 4.0和Xcode 9.0——swift 4在这个问题上有自己的小问题。我有一个带有enum类型的@IBInspectable变量,Xcode 9。0不满意,显示这个“属性不能被标记为@IBInspectable,因为它的类型不能在Objective-c中表示”

@Eporediese answers this problem (for swift3) in part; using a property for the storyboard but a straight enum for the rest of the code. Below is a more complete code set that gives you a property to work with in both cases.

@Eporediese部分回答了这个问题(对于swift3);为故事板使用属性,但为其余代码使用直接枚举。下面是一个更完整的代码集,它为您提供了在这两种情况下都可以使用的属性。

enum StatusShape: Int {
  case Rectangle = 0
  case Triangle = 1
  case Circle = 2
}
var _shape:StatusShape = .Rectangle  // this is the backing variable

#if TARGET_INTERFACE_BUILDER
  @IBInspectable var shape: Int {    // using backing variable as a raw int

    get { return _shape.rawValue }
    set {
      if _shape.rawValue != newValue {
        _shape.rawValue = newValue
      }
    }
}
#else
var shape: StatusShape {  // using backing variable as a typed enum
  get { return _shape }
  set {
    if _shape != newValue {
      _shape = newValue
    }
  }
}
#endif