enum
ist kein vom Interface Builder definiertes Laufzeitattribut. Folgendes wird im Attributinspektor von Interface Builder nicht angezeigt:
enum StatusShape:Int {
case Rectangle = 0
case Triangle = 1
case Circle = 2
}
@IBInspectable var shape:StatusShape = .Rectangle
Aus der Dokumentation: Sie können das IBInspectable-Attribut an jede Eigenschaft in einer Klassendeklaration, Klassenerweiterung oder Kategorie für jeden Typ anhängen, der von den vom Interface Builder definierten Laufzeitattributen unterstützt wird: Boolesche Zahl, Ganzzahl- oder Gleitkommazahl, Zeichenfolge, lokalisierte Zeichenfolge, Rechteck , Punkt, Größe, Farbe, Reichweite und Null.
F: Wie kann ich einen enum
im Attributinspektor des Interface Builder anzeigen?
ios
xcode
swift
interface-builder
SwiftArchitect
quelle
quelle
enum
Fall direkt von IB auswählen zu können , oder einenUIFont
, wie es die nativen UIKit-Objekte können.Antworten:
Swift 3
@IBInspectable
var shape:StatusShape = .Rectangle
erstellt lediglich einen leeren Eintrag in Interface Builder:Verwenden Sie einen Adapter, der als Brücke zwischen Swift und Interface Builder fungiert.
shapeAdapter
ist von IB inspizierbar:// IB: use the adapter @IBInspectable var shapeAdapter:Int { get { return self.shape.rawValue } set( shapeIndex) { self.shape = StatusShape(rawValue: shapeIndex) ?? .Rectangle } }
Im Gegensatz zum Ansatz der bedingten Kompilierung (unter Verwendung
#if TARGET_INTERFACE_BUILDER
)shape
ändert sich der Typ der Variablen nicht mit dem Ziel, sodass möglicherweise weitere Änderungen des Quellcodes erforderlich sind, um dieshape:NSInteger
vs.-shape:StatusShape
Variationen zu bewältigen :// Programmatically: use the enum var shape:StatusShape = .Rectangle
Vollständiger Code
@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 } } }
► Finden Sie diese Lösung auf GitHub .
quelle
shapeAsInt
eine gespeicherte Eigenschaft und keine berechnete Eigenschaft?writeonly
erstellen, aber eine berechnete Eigenschaft erstellt keine Hintergrundinstanzvariable wie Ihre gespeicherte Eigenschaft.Anstatt Ihre überprüfbaren Aufzählungen mit Ints festzulegen, können Sie sie auch mit Zeichenfolgen festlegen. Obwohl diese Option nicht ganz so vorzuziehen ist wie ein Dropdown, bietet sie zumindest ein gewisses Maß an Lesbarkeit.
Nur-Swift-Option:
// 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 } } }
Es ist möglich, dies auch mit Objective-C zum Laufen zu bringen, indem der Aufzählung ein Initialisierer hinzugefügt wird. Der Compiler zeigt jedoch nur den Fehler "nicht verfügbar" für Ihre Nur-IB-Eigenschaften in schnellem Code an.
Schnelle Option mit Obj-C-Kompatibilität:
@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 } } }
quelle
Swift Only
Version: Sie erlaubt einfaches Englisch in IB .Ich kann mich nicht an die schnelle Syntax erinnern, aber so habe ich sie in obj-c gelöst
#if TARGET_INTERFACE_BUILDER @property (nonatomic) IBInspectable NSInteger shape; #else @property (nonatomic) StatusShape shape; #endif
quelle
Für 2020 - @SwiftArchitect Antwort für heute aktualisiert:
Hier ist ein typisches vollständiges Beispiel mit der gesamten heutigen Syntax
import UIKit @IBDesignable class ClipLabels: UILabel { enum Side: Int { case left, right } var side: Side = .left { didSet { common() } } @available(*, unavailable, message: "IB only") @IBInspectable var leftRight01: Int { get { return self.side.rawValue } set(index) { self.side = Side(rawValue: index) ?? .left } }
und nur ein Anwendungsbeispiel ...
switch side { case .left: textColor = .red case .right: textColor = .green }
Für diese wichtige Swift / iOS-Qualitätssicherung
• Die sehr alte Antwort von @SwiftArchitect ist aber vollkommen richtig
• Ich habe es gerade aktualisiert und das kritische "nicht verfügbare" Ding hinzugefügt, das jetzt in Swift möglich ist.
quelle
Dies ist ein alter Thread, aber nützlich. Ich habe meine Antwort auf Swift 4.0 und Xcode 9.0 angepasst - Swift 4 hat seine eigenen kleinen Probleme mit diesem Problem. Ich habe eine @ IBInspectable-Variable mit Aufzählungstyp und Xcode 9.0 ist nicht zufrieden. Dies zeigt mir, dass "Eigenschaft nicht als @IBInspectable markiert werden kann, da ihr Typ in Objective-c nicht dargestellt werden kann".
@Eporediese beantwortet dieses Problem (für swift3) teilweise; Verwenden einer Eigenschaft für das Storyboard, aber einer geraden Aufzählung für den Rest des Codes. Im Folgenden finden Sie einen vollständigeren Codesatz, mit dem Sie in beiden Fällen mit einer Eigenschaft arbeiten können.
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
quelle
Swift 3- Lösung basierend auf 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
quelle
#if TARGET_INTERFACE_BUILDER
Block einschließen, wirkt sich dies nur auf das Rendern in Interface Builder aus, nicht zur Laufzeit. Dies wird wahrscheinlich zu unerwartetem Verhalten führen und Sie werden immer eine Warnung in der Konsole erhalten:Failed to set (statusShapeIB) user defined inspected property ...: this class is not key value coding-compliant for the key statusShapeIB.