web-dev-qa-db-fra.com

Comment créer un IBInspectable de type enum

enum est pas un attribut d'exécution défini par Interface Builder. Les éléments suivants ne s'affichent pas dans l'inspecteur des attributs d'Interface Builder:

enum StatusShape:Int {
    case Rectangle = 0
    case Triangle = 1
    case Circle = 2
}
@IBInspectable var shape:StatusShape = .Rectangle

Dans la documentation: Vous pouvez associer l'attribut IBInspectable à toute propriété d'une déclaration de classe, d'une extension de classe ou d'une catégorie pour tout type pris en charge par les attributs d'exécution définis par Interface Builder: booléen, entier ou flottant. numéro de point, chaîne, chaîne localisée, rectangle, point, taille, couleur, plage et nil

Q: Comment puis-je voir un enum dans l'inspecteur des attributs d'Interface Builder?

73
SwiftArchitect

Swift 3

@ IBInspectable var shape:StatusShape = .Rectangle crée simplement une entrée vide dans Interface Builder:

Not available in IB

Utilisez un adaptateur qui fera office de pont entre Swift et Interface Builder).
shapeAdapter est contrôlable depuis IB:

   // IB: use the adapter
   @IBInspectable var shapeAdapter:Int {
        get {
            return self.shape.rawValue
        }
        set( shapeIndex) {
            self.shape = StatusShape(rawValue: shapeIndex) ?? .Rectangle
        }
    }

Available in IB

Contrairement à la méthode de la compilation conditionnelle (en utilisant #if TARGET_INTERFACE_BUILDER), le type de la variable shape ne change pas avec la cible, nécessitant éventuellement d’autres modifications du code source pour faire face à la shape:NSInteger contre. shape:StatusShape variations:

   // Programmatically: use the enum
   var shape:StatusShape = .Rectangle

Code complet

@IBDesignable
class ViewController: UIViewController {

    enum StatusShape:Int {
        case Rectangle
        case Triangle
        case Circle
    }

    // Programmatically: use the enum
    var shape:StatusShape = .Rectangle

    // IB: use the adapter
    @IBInspectable var shapeAdapter:Int {
        get {
            return self.shape.rawValue
        }
        set( shapeIndex) {
            self.shape = StatusShape(rawValue: shapeIndex) ?? .Rectangle
        }
    }
}

► Trouvez cette solution sur GitHub .

69
SwiftArchitect

Au lieu de définir vos enums inspectables avec ints, vous pouvez également les définir avec des chaînes. Bien que cela ne soit pas aussi préférable qu’un menu déroulant, cette option offre au moins un certain degré de lisibilité.

Option Swift uniquement:

// 1. Set up your enum
enum Shape: String {
    case Rectangle = "rectangle" // lowercase to make it case-insensitive
    case Triangle = "triangle"
    case Circle = "circle"
}


// 2. Then set up a stored property, which will be for use in code
var shape = Shape.Rectangle // default shape


// 3. And another stored property which will only be accessible in IB (because the "unavailable" attribute prevents its use in code)
@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'shape' instead.")
@IBInspectable var shapeName: String? {
    willSet {
        // Ensure user enters a valid shape while making it lowercase.
        // Ignore input if not valid.
        if let newShape = Shape(rawValue: newValue?.lowercased() ?? "") {
            shape = newShape
        }
    }
}

Il est également possible d'obtenir que cela fonctionne également avec object-c, en ajoutant un initialiseur à l'énumération. Cependant, le compilateur n'affichera que l'erreur "indisponible" pour vos propriétés uniquement dans IB dans le code Swift.

Option Swift avec Compatibilité Obj-C:

@objc enum Shape: Int {
    case None
    case Rectangle
    case Triangle
    case Circle

    init(named shapeName: String) {
        switch shapeName.lowercased() {
        case "rectangle": self = .Rectangle
        case "triangle": self = .Triangle
        case "circle": self = .Circle
        default: self = .None
        }
    }
}

var shape = Shape.Rectangle // default shape

@available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'shape' instead.")
@IBInspectable var shapeName: String? {
    willSet {
        if let newShape = Shape(rawValue: newValue?.lowercased() ?? "") {
            shape = newShape
        }
    }
}
36
DonVaughn

Je ne me souviens pas de la syntaxe Swift, mais voici comment je l'ai résolue dans obj-c

#if TARGET_INTERFACE_BUILDER
@property (nonatomic) IBInspectable NSInteger shape;
#else
@property (nonatomic) StatusShape shape;
#endif
20
Jason Bobier

C'est un vieux fil mais utile. J'ai adapté ma réponse à Swift 4.0 et Xcode 9.0 - Swift 4 a ses propres petits problèmes avec ce problème. J'ai une variable @IBInspectable avec enum type et Xcode 9.0 ne sont pas satisfaits, ce qui signifie que "La propriété ne peut pas être marquée @IBInspectable car son type ne peut pas être représenté dans Objective-c"

@Eporediese répond à ce problème (pour Swift3) en partie; en utilisant une propriété pour le storyboard, mais une énumération simple pour le reste du code. Vous trouverez ci-dessous un ensemble de codes plus complet qui vous donne une propriété à utiliser dans les deux cas.

enum StatusShape: Int {
  case Rectangle = 0
  case Triangle = 1
  case Circle = 2
}
var _shape:StatusShape = .Rectangle  // this is the backing variable

#if TARGET_INTERFACE_BUILDER
  @IBInspectable var shape: Int {    // using backing variable as a raw int

    get { return _shape.rawValue }
    set {
      if _shape.rawValue != newValue {
        _shape.rawValue = newValue
      }
    }
}
#else
var shape: StatusShape {  // using backing variable as a typed enum
  get { return _shape }
  set {
    if _shape != newValue {
      _shape = newValue
    }
  }
}
#endif
3
Ohmy

Swift 3 solution basée sur SwiftArchitect

enum StatusShape: Int {
    case rectangle, triangle, circle
}
var statusShape: StatusShape = .rectangle
#if TARGET_INTERFACE_BUILDER
@IBInspectable var statusShapeIB: Int {
    get { 
        return statusShape.rawValue 
    }
    set { 
        guard let statusShape = StatusShape(rawValue: newValue) else { return }
        self.statusShape = statusShape
    }
}   //convenience var, enum not inspectable
#endif
1
Eporediese
I just removed @IBInspectable keyword 

d'où cette erreur est apparue (c'était deux fois pour moi). Pour ce faire, vous devrez déverrouiller la bibliothèque VHBoomMenuButton afin de pouvoir apporter des modifications.

and its work  
0
Shakeel Ahmed