Me gustaría crear un @IBInspectable
elemento como se ve en la imagen de abajo:
mi idea es usar algo como enum como tipo para @IBInspectable
, pero parece que no es el caso, ¿alguna idea de cómo implementar un elemento como este?
EDITAR:
Parece que @IBInspectable
solo admite estos tipos:
Int
CGFloat
Double
String
Bool
CGPoint
CGSize
CGRect
UIColor
UIImage
gorrón
Respuestas:
Eso no es posible (por ahora). Solo puede usar los tipos que ve en la sección Atributos de tiempo de ejecución definidos por el usuario .
Del documento de Apple :
fuente
Otra solución alternativa para esto es alterar cómo aparece una propiedad de enumeración en el constructor de interfaces. Por ejemplo:
#if TARGET_INTERFACE_BUILDER @property (nonatomic, assign) IBInspectable NSInteger fontWeight; #else @property (nonatomic, assign) FontWeight fontWeight; #endif
Esto asume una enumeración llamada FontWeight. Se basa en el hecho de que las enumeraciones y sus valores enteros sin procesar se pueden usar indistintamente en Objective-C. Después de hacer esto, puede especificar un número entero en el generador de interfaces para la propiedad que no es ideal, pero funciona y conserva una pequeña cantidad de seguridad de tipos cuando se usa la misma propiedad mediante programación.
Esta es una mejor alternativa que declarar una propiedad de entero separada porque no necesita escribir lógica adicional para manejar una segunda propiedad de entero que también podría usarse para lograr lo mismo.
Sin embargo, esto no funciona con Swift porque no podemos convertir implícitamente de un entero a una enumeración. Cualquier pensamiento sobre la solución sería apreciado.
fuente
Hago esto usando un valor Inspectable NSInteger y anulo el setter para permitirle establecer la enumeración. Esto tiene la limitación de no usar una lista emergente y si cambia los valores de enumeración, las opciones de la interfaz no se actualizarán para coincidir.
Ejemplo.
En archivo de encabezado:
typedef NS_ENUM(NSInteger, LabelStyle) { LabelStyleContent = 0, //Default to content label LabelStyleHeader, }; ... @property LabelStyle labelStyle; @property (nonatomic, setter=setLabelAsInt:) IBInspectable NSInteger labelStyleLink;
En el archivo de implementación:
- (void)setLabelAsInt:(NSInteger)value { self.labelStyle = (LabelStyle)value; }
Opcionalmente, puede agregar algo de lógica allí para asegurarse de que se establezca en un valor válido
fuente
Sikhapol es correcto, las enumeraciones aún no son compatibles y tampoco en xCode 9. Creo que el enfoque más seguro es usar enumeraciones como cadenas e implementar una var IBInspectable "sombra" (privada). Aquí hay un ejemplo de un elemento BarBtnPaintCode que representa un elemento de botón de barra que se puede diseñar con un icono personalizado (que se hace con PaintCode) dentro de Interface Builder (swift 4).
En la construcción de la interfaz, simplemente ingrese la cadena (idéntica al valor de enumeración), lo que lo mantiene claro (si está ingresando números, nadie sabe lo que significan)
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 } } }
fuente
Como respondió @sikhapol, esto no es posible. La solución alternativa que utilizo para esto es tener un montón de
IBInspectable
bools en mi clase y simplemente seleccionar uno en el generador de interfaces. Para mayor seguridad de que no se configuran varios, agregue unNSAssert
en el configurador para cada uno.- (void)setSomeBool:(BOOL)flag { if (flag) { NSAssert(!_someOtherFlag && !_someThirdFlag, @"Only one flag can be set"); } }
Esto es un poco tedioso y un poco descuidado en mi opinión, pero es la única forma de lograr este tipo de comportamiento que se me ocurre.
fuente
Quiero agregar que los identificadores de an
enum
no están disponibles en tiempo de ejecución para nadie en Objective-C. Por lo tanto, no puede haber la posibilidad de mostrarlo en cualquier lugar.fuente
Mi solución fue hacer:
@IBInspectable var keyboardType = UIKeyboardType.default.rawValue { didSet { textField.keyboardType = UIKeyboardType(rawValue: keyboardType)! } }
En el propio IB, deberá establecer un int en el campo keyboardType
fuente