Eu gostaria de criar um @IBInspectable
elemento como você pode ver na imagem abaixo:
minha idéia é usar algo como enum como tipo para @IBInspectable
, mas parece que não é o caso, alguma idéia de como implementar um elemento como este?
EDITAR:
Parece que @IBInspectable
suporta apenas estes tipos:
Int
CGFloat
Double
String
Bool
CGPoint
CGSize
CGRect
UIColor
UIImage
vadio
Respostas:
Isso não é possível (por enquanto). Você só pode usar os tipos que vê na seção Atributos de tempo de execução definidos pelo usuário .
Do documento da Apple :
fonte
Outra solução alternativa para isso é alterar como uma propriedade de enumeração aparece para o construtor de interface. Por exemplo:
#if TARGET_INTERFACE_BUILDER @property (nonatomic, assign) IBInspectable NSInteger fontWeight; #else @property (nonatomic, assign) FontWeight fontWeight; #endif
Isso pressupõe um enum chamado FontWeight. Ele se baseia no fato de que enums e seus valores inteiros brutos podem ser usados de forma intercambiável em Objective-C. Depois de fazer isso, você pode especificar um inteiro no construtor de interface para a propriedade que não é ideal, mas funciona e mantém uma pequena quantidade de segurança de tipo ao usar a mesma propriedade de forma programática.
Esta é uma alternativa melhor do que declarar uma propriedade inteira separada porque você não precisa escrever lógica extra para lidar com uma segunda propriedade inteira que também pode ser usada para realizar a mesma coisa.
No entanto, isso não funciona com o Swift porque não podemos converter implicitamente de um inteiro para um enum. Quaisquer pensamentos sobre a resolução que serão apreciados.
fonte
Eu faço isso usando um valor NSInteger Inspectable e substituo o setter para permitir que ele defina o enum. Isso tem a limitação de não usar uma lista pop-up e, se você alterar os valores enum, as opções da interface não serão atualizadas para corresponder.
Exemplo.
No arquivo de cabeçalho:
typedef NS_ENUM(NSInteger, LabelStyle) { LabelStyleContent = 0, //Default to content label LabelStyleHeader, }; ... @property LabelStyle labelStyle; @property (nonatomic, setter=setLabelAsInt:) IBInspectable NSInteger labelStyleLink;
No arquivo de implementação:
- (void)setLabelAsInt:(NSInteger)value { self.labelStyle = (LabelStyle)value; }
Você pode opcionalmente adicionar alguma lógica lá para garantir que está sendo definido com um valor válido
fonte
Sikhapol está correto, enums ainda não são suportados também não no xCode 9. Eu acredito que a abordagem mais segura é usar enums como strings e implementar uma "sombra" (privada) IBInspectable var. Aqui está um exemplo de um item BarBtnPaintCode que representa um item Barbutton que pode ser estilizado com um ícone personalizado (isso é feito usando PaintCode) dentro do Interface Builder (swift 4).
Na construção da interface, você apenas insere a string (idêntica ao valor enum), que o mantém claro (se você está inserindo números, ninguém sabe o que eles significam)
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 } } }
fonte
Como @sikhapol respondeu, isso não é possível. A solução que uso para isso é ter um monte de
IBInspectable
bools em minha classe e apenas selecionar um no construtor de interface. Para aumentar a segurança de que vários não sejam configurados, adicione umNSAssert
no configurador para cada um.- (void)setSomeBool:(BOOL)flag { if (flag) { NSAssert(!_someOtherFlag && !_someThirdFlag, @"Only one flag can be set"); } }
Isso é um pouco entediante e um pouco desleixado OMI, mas é a única maneira de realizar esse tipo de comportamento que eu consigo pensar
fonte
Quero acrescentar que os identificadores de um
enum
não estão disponíveis em tempo de execução para ninguém em Objective-C. Portanto, não pode haver a possibilidade de exibi-lo em qualquer lugar.fonte
Minha solução foi fazer:
@IBInspectable var keyboardType = UIKeyboardType.default.rawValue { didSet { textField.keyboardType = UIKeyboardType(rawValue: keyboardType)! } }
No próprio IB, você precisará definir um int no campo keyboardType
fonte