ios 如何创建枚举类型的 IBInspectable

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27432736/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 03:59:52  来源:igfitidea点击:

How to create an IBInspectable of type enum

iosxcodeswiftinterface-builder

提问by SwiftArchitect

enumis notan Interface Builder defined runtime attribute. The following does not show in Interface Builder's Attributes Inspector:

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

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 属性附加到接口生成器定义的运行时属性支持的任何类型的类声明、类扩展或类别中的任何属性:布尔值、整数或浮点数、字符串、本地化字符串、矩形、点、大小、颜色、范围和零。

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

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

回答by SwiftArchitect

Swift 3

斯威夫特 3

@IBInspectablevar shape:StatusShape = .Rectanglemerely creates a blank entry in Interface Builder:

@IBInspectablevar shape:StatusShape = .Rectangle只是在 Interface Builder 中创建一个空白条目:

Not available in IB

在 IB 中不可用

Use an adapter, which will acts as a bridgebetween Swift and Interface Builder.
shapeAdapteris inspectable from 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
        }
    }

Available in IB

在IB中可用

Unlike the conditional compilation approach (using #if TARGET_INTERFACE_BUILDER), the type of the shapevariable does not change with the target, potentially requiring further source code changes to cope with the shape:NSIntegervs. shape:StatusShapevariations:

与条件编译方法(使用#if TARGET_INTERFACE_BUILDER)不同,shape变量的类型不会随着目标而改变,可能需要进一步更改源代码以应对shape:NSIntegervs.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 上找到此解决方案。

回答by DonVaughn

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:

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

It ispossible 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.

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

Swift Option with Obj-C Compatibility:

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

回答by Jason Bobier

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

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

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

回答by Ohmy

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 在这个问题上有自己的小问题。我有一个枚举类型的@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

回答by Fattie

For 2020

2020年

Here's a typical full example with all of today's syntax

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

enter image description here

在此处输入图片说明

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

and just an example of use ...

并且只是一个使用示例......

    // just an example of using it at bringup...

    override init(frame: CGRect) {
        super.init(frame: frame)
        common()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        common()
    }

    private func common() {
        font = .monospacedDigitSystemFont(ofSize: 12, weight: .medium)
        switch side {
            case .left:
                textColor = .red
            case .right:
                textColor = .green
        }
    }
}

For this critical Swift/iOS QA,

对于这个关键的 Swift/iOS QA,

? the very old answer of @SwiftArchitect is perfectly correct but

? @SwiftArchitect 的旧答案是完全正确的,但是

? I've just updated it and added the critical "unavailable" thing, which is now possible in Swift.

? 我刚刚更新了它并添加了关键的“不可用”的东西,现在在 Swift 中是可能的。

回答by Eporediese

Swift 3solution 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