J'aimerais créer @IBInspectable
élément comme vous le voyez sur l'image ci-dessous:
mon idée est d'utiliser quelque chose comme enum comme type pour @IBInspectable
, mais il semble que ce n'est pas le cas, des idées comment implémenter un élément comme celui-ci?
ÉDITER:
Il semble que @IBInspectable
seuls ces types soient pris en charge:
Int
CGFloat
Double
String
Bool
CGPoint
CGSize
CGRect
UIColor
UIImage
décevoir
Réponses:
Ce n'est pas possible (pour l'instant). Vous ne pouvez utiliser que les types que vous voyez dans la section Attributs d'exécution définis par l'utilisateur .
D'après le document d'Apple :
la source
Une autre solution consiste à modifier l'apparence d'une propriété d'énumération au générateur d'interface. Par exemple:
#if TARGET_INTERFACE_BUILDER @property (nonatomic, assign) IBInspectable NSInteger fontWeight; #else @property (nonatomic, assign) FontWeight fontWeight; #endif
Cela suppose une énumération appelée FontWeight. Il repose sur le fait que les énumérations et leurs valeurs entières brutes peuvent être utilisées de manière interchangeable en Objective-C. Après cela, vous pouvez spécifier un entier dans le générateur d'interface pour la propriété qui n'est pas idéal, mais qui fonctionne et conserve une petite quantité de sécurité de type lors de l'utilisation de la même propriété par programme.
C'est une meilleure alternative que de déclarer une propriété entière distincte car vous n'avez pas besoin d'écrire une logique supplémentaire pour gérer une deuxième propriété entière qui pourrait également être utilisée pour accomplir la même chose.
Cependant, cela ne fonctionne pas avec Swift car nous ne pouvons pas convertir implicitement d'un entier en une énumération. Toute réflexion sur la solution serait appréciée.
la source
Je fais cela en utilisant une valeur NSInteger Inspectable et remplace le setter pour lui permettre de définir l'énumération. Cela a la limitation de ne pas utiliser de liste contextuelle et si vous modifiez vos valeurs d'énumération, les options d'interface ne seront pas mises à jour pour correspondre.
Exemple.
Dans le fichier d'en-tête:
typedef NS_ENUM(NSInteger, LabelStyle) { LabelStyleContent = 0, //Default to content label LabelStyleHeader, }; ... @property LabelStyle labelStyle; @property (nonatomic, setter=setLabelAsInt:) IBInspectable NSInteger labelStyleLink;
Dans le fichier d'implémentation:
- (void)setLabelAsInt:(NSInteger)value { self.labelStyle = (LabelStyle)value; }
Vous pouvez éventuellement ajouter de la logique pour vous assurer qu'il est défini sur une valeur valide
la source
Sikhapol est correct, les énumérations ne sont pas encore prises en charge également pas dans xCode 9. Je crois que l'approche la plus sûre consiste à utiliser les énumérations comme chaînes et à implémenter une variable IBInspectable "shadow" (privée). Voici un exemple d'élément BarBtnPaintCode qui représente un élément de bouton de barre qui peut être stylisé avec une icône personnalisée (cela est fait à l'aide de PaintCode) directement dans Interface Builder (swift 4).
Dans la construction de l'interface, vous entrez simplement la chaîne (identique à la valeur d'énumération), ce qui la maintient claire (si vous entrez des nombres, personne ne sait ce qu'ils signifient)
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 } } }
la source
Comme @sikhapol a répondu, ce n'est pas possible. La solution de contournement que j'utilise pour cela est d'avoir un tas de
IBInspectable
booléens dans ma classe et d'en sélectionner un dans le générateur d'interface. Pour plus de sécurité que plusieurs ne sont pas définis, ajoutez unNSAssert
dans le setter pour chacun.- (void)setSomeBool:(BOOL)flag { if (flag) { NSAssert(!_someOtherFlag && !_someThirdFlag, @"Only one flag can be set"); } }
C'est un peu fastidieux et un peu bâclé de l'OMI, mais c'est le seul moyen d'accomplir ce genre de comportement auquel je peux penser
la source
Je veux ajouter que les identifiants d'un
enum
ne sont pas disponibles à l'exécution pour quiconque dans Objective-C. Il ne peut donc pas être possible de l'afficher n'importe où.la source
Ma solution était de faire:
@IBInspectable var keyboardType = UIKeyboardType.default.rawValue { didSet { textField.keyboardType = UIKeyboardType(rawValue: keyboardType)! } }
Sur l'IB lui-même, vous devrez définir un int dans le champ keyboardType
la source