【问题标题】:@IBInspectable with enum?@IBInspectable 与枚举?
【发布时间】:2018-08-07 17:37:29
【问题描述】:

我想创建@IBInspectable 元素,如下图所示:

我的想法是使用枚举之类的东西作为@IBInspectable 的类型,但看起来情况并非如此,有什么想法如何实现这样的元素吗?

编辑:

看起来@IBInspectable 只支持这些类型:

  • Int
  • CGFloat
  • Double
  • String
  • Bool
  • CGPoint
  • CGSize
  • CGRect
  • UIColor
  • UIImage

无赖

【问题讨论】:

  • 一种解决方法是在要设置的值前面放置一个可检查的计算属性。当然,它仍然不会神奇地出现在 Interface Builder 中作为枚举值的弹出菜单;但至少你可以定义一个可检查的值并用它来设置一个枚举。
  • 在今年的 WWDC 上,我向开发者工具实验室的一位 Apple 工程师询问了这个问题。他说他同意这将是一个很棒的功能,但目前还不可能。他建议我在bugreport.apple.com 提交雷达,我照做了。它已作为问题 15505220 的副本关闭,但我强烈建议人们提出类似的问题。如果有足够多的人抱怨,这些问题通常会得到解决。
  • 这个问题和stackoverflow.com/questions/27432736/…有什么不同
  • 借助 SwiftUI 和 Xcode 11 中的新 Canvas,这似乎永远不会出现在 Apple 的路线图上

标签: ios objective-c iphone xcode swift


【解决方案1】:

这是不可能的(目前)。您只能使用在用户定义的运行时属性部分中看到的那些类型。

来自苹果的doc

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

【讨论】:

  • 当我想使用枚举时,我给枚举值明确赋值(= 1、= 2 等)。在处理程序中,如果来自 IB 的值不是来自枚举的值之一,我会添加一个断言。不支持枚举很烦人,但这个技巧至少使它们更有用。
  • 枚举是一个整数。
【解决方案2】:

另一个解决方法是改变枚举属性在界面构建器中的显示方式。例如:

#if TARGET_INTERFACE_BUILDER
@property (nonatomic, assign) IBInspectable NSInteger fontWeight;
#else
@property (nonatomic, assign) FontWeight fontWeight;
#endif

这假定一个名为 FontWeight 的枚举。它依赖于枚举及其原始整数值在 Objective-C 中可以互换使用的事实。完成此操作后,您可以在 Interface builder 中为该属性指定一个整数,该整数并不理想,但可以工作,并且在以编程方式使用相同属性时保留少量类型安全性。

这比声明一个单独的整数属性更好,因为您不需要编写额外的逻辑来处理第二个整数属性,它也可以用来完成同样的事情。

但是,这不适用于 Swift,因为我们无法从整数隐式转换为枚举。任何有关解决该问题的想法将不胜感激。

【讨论】:

  • 我真的认为这在 Swift 中确实有效,但在进一步的测试中......没有
【解决方案3】:

我使用 Inspectable NSInteger 值执行此操作并覆盖设置器以允许它设置枚举。这有不使用弹出列表的限制,如果您更改枚举值,则界面选项将不会更新以匹配。

示例。

在头文件中:

typedef NS_ENUM(NSInteger, LabelStyle)
{
    LabelStyleContent = 0, //Default to content label
    LabelStyleHeader,
};

...

@property LabelStyle labelStyle;
@property (nonatomic, setter=setLabelAsInt:) IBInspectable NSInteger labelStyleLink;

在实现文件中:

- (void)setLabelAsInt:(NSInteger)value
{
    self.labelStyle = (LabelStyle)value;
}

您可以选择在其中添加一些逻辑以确保将其设置为有效值

【讨论】:

  • 不知道为什么这被否决了。似乎是解决问题的好方法。
  • 谢谢@Fogmeister - 我现在实际上是在一个应用程序中使用这个实现:)
【解决方案4】:

Sikhapol 是正确的,在 xCode 9 中也不支持枚举。我相信最安全的方法是将枚举用作字符串并实现“影子”(私有)IBInspectable var。这是一个 BarBtnPaintCode 项目的示例,它表示一个 barbutton 项目,可以在 Interface Builder (swift 4) 中使用自定义图标(使用 PaintCode 完成)设置样式。

在界面构建中,您只需输入字符串(与枚举值相同),这样可以保持清晰(如果您输入的数字没有人知道它们的含义)

class BarBtnPaintCode: BarBtnPaintCodeBase {

    enum TypeOfButton: String {
        case cancel
        case ok
        case done
        case edit
        case scanQr
        //values used for tracking if wrong input is used
        case uninitializedLoadedFromStoryboard
        case unknown
    }

    var typeOfButton = TypeOfButton.uninitializedLoadedFromStoryboard

    @IBInspectable private var type : String {
        set {
            typeOfButton = TypeOfButton(rawValue: newValue) ?? .unknown
            setup()
        }
        get {
            return typeOfButton.rawValue
        }
    }

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

    init(typeOfButton: TypeOfButton, title: String? = nil, target: AnyObject?, action: Selector) {
        super.init()
        self.typeOfButton = typeOfButton
        setup()
        self.target = target
        self.action = action
        self.title  = title
    }

    override func setup() {
        //same for all
        setTitleTextAttributes([NSAttributedStringKey.font : UIFont.defaultFont(size: 15)],for: UIControlState.normal)
        //depending on the type
        switch typeOfButton {
        case .cancel  :
            title = nil
            image = PaintCode.imageOfBarbtn_cancel(language: currentVisibleLanguage)
        case .ok      :
            title = nil
            image = PaintCode.imageOfBarbtn_ok(language: currentVisibleLanguage)
        case .done    :
            title = nil
            image = PaintCode.imageOfBarbtn_done(language: currentVisibleLanguage)
        case .edit    :
            title = nil
            image = PaintCode.imageOfBarbtn_edit(language: currentVisibleLanguage)
        case .uninitializedLoadedFromStoryboard :
            title = nil
            image = PaintCode.imageOfBarbtn_unknown
            break
        case .unknown:
            log.error("BarBtnPaintCode used with unrecognized type")
            title = nil
            image = PaintCode.imageOfBarbtn_unknown
            break
        }

    }

}

【讨论】:

  • 很棒的解决方案,用 Swift 4 实现没有问题。如果您使用它,请注意在故事板和 xibs 中正确拼写类型
【解决方案5】:

正如@sikhapol 回答的那样,这是不可能的。我为此使用的解决方法是在我的班级中有一堆IBInspectable bool,然后在界面生成器中选择一个。为了增加未设置多个的安全性,请在每个设置器中添加一个NSAssert

- (void)setSomeBool:(BOOL)flag
{
    if (flag)
    {
        NSAssert(!_someOtherFlag && !_someThirdFlag, @"Only one flag can be set");
    }
}

这有点乏味,有点马虎IMO,但这是我能想到的完成这种行为的唯一方法

【讨论】:

    【解决方案6】:

    我想补充一点,enum 的标识符在运行时不适用于 Objective-C 中的任何人。所以不可能在任何地方显示它。

    【讨论】:

      【解决方案7】:

      我的解决方案是:

      @IBInspectable  
      var keyboardType = UIKeyboardType.default.rawValue {
              didSet { 
                   textField.keyboardType = UIKeyboardType(rawValue: keyboardType)! 
              }
      }
      

      在 IB 本身上,您需要在 keyboardType 字段中设置一个 int

      【讨论】:

        猜你喜欢
        • 2015-02-10
        • 1970-01-01
        • 2012-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多