如何创建枚举类型的IBInspectable


83

enum接口生成器中定义的运行时属性。Interface Builder的“属性”检查器中未显示以下内容:

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

从文档中获得: 可以将IBInspectable属性附加到接口声明,类扩展名或类别中的任意属性,以用于Interface Builder定义的运行时属性支持的任何类型:布尔值,整数或浮点数,字符串,本地化字符串,矩形,点,大小,颜色,范围和零。

问:如何enum在Interface Builder的Attributes Inspector中看到一个?


1
该列表中的枚举在哪里?您为什么认为可以使用枚举?
Paulw11

12
我想能够enum直接从IB中选择一个案例,或者UIFont像本机UIKit对象一样选择一个案例,将是一个很好的选择。
SwiftArchitect15年

Answers:


75

迅捷3

@IBInspectable var shape:StatusShape = .Rectangle仅在Interface Builder中创建一个空白条目:

在IB中不可用

使用适配器,它将充当Swift和Interface Builder之间的桥梁
shapeAdapter可从IB检查:

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

IB可用

与条件编译方法(使用#if TARGET_INTERFACE_BUILDER)不同,shape变量的类型不会随目标的变化而变化,可能需要进一步更改源代码以应对shape:NSIntegervs.shape:StatusShape变化:

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

完整的代码

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

►在GitHub上找到此解决方案。


为什么要保留shapeAsInt为存储属性而不是计算属性?
nhgrif 2015年

对。writeonly虽然您不能创建属性...但是计算属性不会像存储的属性那样创建后备实例变量。
nhgrif

添加了@nhgrif提出的无后备存储解决方案。
SwiftArchitect

1
不好意思。我以为我对TARGET_INTERFACE_BUILDER有一个可行的解决方案,但被误导了。对不起,好运在这里SO
丹Rosenstark

快进到2017年,这个问题仍然保持不变吗?
NoSixties

40

除了用int设置可检查的枚举外,还可以使用字符串设置它们。尽管不如下拉菜单那么可取,但至少此选项提供了一定程度的可读性。

仅Swift选项:

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

可能的也是得到这个用Objective-C的工作,以及通过增加一个初始化的枚举。但是,编译器仅会在swift代码中显示仅IB属性的“不可用”错误。

具有Obj-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
        }
    }
}

2
我喜欢这个Swift Only版本:它允许在IB中使用简单的英语。
SwiftArchitect

有谁知道如何使用这种方法在IB中以字符串形式显示选项?
airowe

我想知道如何使用下拉菜单完成此操作。
Wael

19

我不记得快速的语法,但这就是我在obj-c中解决它的方式

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

1
我具有条件汇编的唯一位置是声明中的那个位置。因为枚举是obj-c中的整数,所以其他任何地方都没有条件汇编。一个地方的时候苹果修复了这个(假设他们的意志。)删除
贾森Bobier

这是一个机智且令人敬畏的解决方案,在此处提到了nshipster.com/ibinspectable-ibdesignable
Dan Rosenstark 2015年

7

对于2020年-@SwiftArchitect答案今天已更新:

这是一个具有当今所有语法的典型完整示例

在此处输入图片说明

import UIKit

@IBDesignable class ClipLabels: UILabel {
    
    enum Side: Int { case left, right }
    
    var side: Side = .left {
        didSet {
            common()
        }
    }
    
    @available(*, unavailable, message: "IB only")
    @IBInspectable var leftRight01: Int {
        get {
            return self.side.rawValue
        }
        set(index) {
            self.side = Side(rawValue: index) ?? .left
        }
    }
    

只是一个使用示例...

switch side {
    case .left:
        textColor = .red
    case .right:
        textColor = .green
    }

对于这个至关重要的Swift / iOS质量检查,

•@SwiftArchitect的非常老的答案是完全正确的,但

•我刚刚更新了它,并添加了关键的“不可用”内容,现在在Swift中可以实现。


4

这是一个旧线程,但很有用。我已将答案调整为swift 4.0和Xcode 9.0-Swift 4在此问题上有自己的小问题。我有一个枚举类型为@IBInspectable的变量,而Xcode 9.0不满意,向我显示了此“属性无法标记为@IBInspectable,因为其类型无法在Objective-c中表示”

@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

2

基于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

2
如果将此IB-inspectable属性包装在一个#if TARGET_INTERFACE_BUILDER块中,它将仅影响Interface Builder中的呈现,而不影响运行时。这可能会导致意外行为,并且您将始终在控制台中收到警告:Failed to set (statusShapeIB) user defined inspected property ...: this class is not key value coding-compliant for the key statusShapeIB.
Mischa
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.