@IBInspectable与enum?

时间:2015-02-26 18:02:55

标签: ios objective-c iphone xcode swift

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

enter image description here

我的想法是使用枚举类似于@IBInspectable的类型,但看起来并非如此,任何想法如何实现这样的元素?

编辑:

看起来@IBInspectable仅支持以下类型:

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

长号

7 个答案:

答案 0 :(得分:25)

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

来自Apple的doc

  

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

答案 1 :(得分:21)

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

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

这假设一个名为FontWeight的枚举。它依赖于以下事实:在Objective-C中,枚举及其原始整数值可以在某种程度上互换使用。执行此操作后,您可以在“界面”构建器中为该属性指定一个不太理想的整数但可以正常工作,并且在以编程方式使用相同属性时保留少量类型安全性。

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

但是,这不适用于Swift,因为我们无法从整数隐式地转换为枚举。任何解决问题的想法都会受到赞赏。

答案 2 :(得分:7)

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

实施例

在标题文件中:

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

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

答案 3 :(得分:1)

@sikhapol回答说,这是不可能的。我使用的解决方法是在我的类中有一堆IBInspectable bool,只需在界面构建器中选择一个。为了增加安全性,未设置多个,请在setter中为每个添加NSAssert

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

这有点单调乏味且有点草率的IMO,但这是实现我能想到的这种行为的唯一方法

答案 4 :(得分:1)

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

答案 5 :(得分:1)

我的解决方案是:

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

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

答案 6 :(得分:1)

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

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

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
        }

    }

}