@IBInspectable with enum?

前端 未结 7 1368
旧时难觅i
旧时难觅i 2020-12-24 04:11

I\'d like to create @IBInspectable element as you see at the picture below :

\"enter

相关标签:
7条回答
  • 2020-12-24 04:46

    I want to add that the identifiers of an enum are not available at runtime for anybody in Objective-C. So there cannot be a possibility to display it anywhere.

    0 讨论(0)
  • 2020-12-24 04:46

    My solution was to do :

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

    On the IB itself, you will need to set an int in the keyboardType field

    0 讨论(0)
  • 2020-12-24 04:47

    That's not possible (for now). You can only use those types that you see in User Defined Runtime Attributes section.

    From Apple's doc:

    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.

    0 讨论(0)
  • 2020-12-24 04:47

    Another work-around for this is to alter how an enumeration property appears to interface builder. For example:

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

    This assumes an enum called FontWeight. It relies on the fact that enums and their raw integer values can be used somewhat interchangeably in Objective-C. After doing this you are able to specify an integer in Interface builder for the property which is not ideal, but works, and retains a small amount of type safety when using the same property programatically.

    This is a better alternative than declaring a separate integer property because you don't need to write extra logic to handle a second integer property which could also be used to accomplish the same thing.

    However, this does not work with Swift because we're not able to implicitly cast from an integer to an enum. Any thoughts on solving that would be appreciated.

    0 讨论(0)
  • 2020-12-24 04:48

    Sikhapol is correct, enums are not yet supported also not in xCode 9. I believe the safest approach is to use enums as strings and implement a "shadow" (private) IBInspectable var. Here is an example of a BarBtnPaintCode item which represents a barbutton item that can be styled with a custom icon (that is done using PaintCode) right inside Interface Builder (swift 4).

    In interface build you just enter the string (identical to the enum value), which keeps it clear (if you are entering numbers nobody knows what they mean)

    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
            }
    
        }
    
    }
    
    0 讨论(0)
  • 2020-12-24 04:57

    As @sikhapol answered, this is not possible. The workaround I use for this is to have a bunch of IBInspectable bools in my class and just select one in interface builder. For added security that multiple ones are not set, add an NSAssert in the setter for each one.

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

    This is a little tedious and a bit sloppy IMO, but it's the only way to accomplish this kind of behavior that I can think of

    0 讨论(0)
提交回复
热议问题