enum
to nie atrybut definiuje czas pracy interfejsu Builder. Poniższe informacje nie są wyświetlane w Inspektorze atrybutów programu Interface Builder:
enum StatusShape:Int {
case Rectangle = 0
case Triangle = 1
case Circle = 2
}
@IBInspectable var shape:StatusShape = .Rectangle
Z dokumentacji: Możesz dołączyć atrybut IBInspectable do dowolnej właściwości w deklaracji klasy, rozszerzeniu klasy lub kategorii dla dowolnego typu, który jest obsługiwany przez zdefiniowane w programie Interface Builder atrybuty środowiska wykonawczego: wartość logiczna, liczba całkowita lub zmiennoprzecinkowa, ciąg, zlokalizowany ciąg, prostokąt , punkt, rozmiar, kolor, zakres i zero.
P: Jak mogę zobaczyć enum
Inspektor atrybutów w Interface Builder?
ios
xcode
swift
interface-builder
SwiftArchitect
źródło
źródło
enum
przypadek prosto z IB, jak przypuszczam, lub aUIFont
, tak jak natywne obiekty UIKit.Odpowiedzi:
Szybki 3
@IBInspectable
var shape:StatusShape = .Rectangle
po prostu tworzy pusty wpis w Interface Builder:Użyj adaptera, który będzie działał jako pomost między Swift a Interface Builder.
shapeAdapter
można sprawdzić od IB:// IB: use the adapter @IBInspectable var shapeAdapter:Int { get { return self.shape.rawValue } set( shapeIndex) { self.shape = StatusShape(rawValue: shapeIndex) ?? .Rectangle } }
W przeciwieństwie do metody kompilacji warunkowej (przy użyciu
#if TARGET_INTERFACE_BUILDER
), typshape
zmiennej nie zmienia się wraz z celem, potencjalnie wymagając dalszych zmian w kodzie źródłowym, aby poradzić sobie z wersjamishape:NSInteger
vs.shape:StatusShape
// Programmatically: use the enum var shape:StatusShape = .Rectangle
Kompletny kod
@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 } } }
► Znajdź to rozwiązanie na GitHub .
źródło
shapeAsInt
jako własność przechowywaną, a nie obliczoną?writeonly
... ale właściwość obliczona nie tworzy zmiennej instancji zapasowej, tak jak robi to twoja właściwość przechowywana.Zamiast ustawiać możliwe do sprawdzenia wyliczenia z wartościami int, możesz również ustawić je za pomocą ciągów. Chociaż nie jest tak preferowana jak lista rozwijana, przynajmniej ta opcja zapewnia pewien poziom czytelności.
Opcja tylko w wersji Swift:
// 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 } } }
Możliwe jest również, aby to działało również z celem-c, dodając inicjator do wyliczenia. Jednak kompilator pokaże tylko błąd „niedostępny” dla właściwości tylko IB w kodzie Swift.
Opcja Swift z kompatybilnością 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 } } }
źródło
Swift Only
wersja: pozwala na zwykły angielski w IB .Nie pamiętam szybkiej składni, ale tak to rozwiązałem w obj-c
#if TARGET_INTERFACE_BUILDER @property (nonatomic) IBInspectable NSInteger shape; #else @property (nonatomic) StatusShape shape; #endif
źródło
Na rok 2020 - odpowiedź @SwiftArchitect zaktualizowana na dziś:
Oto typowy pełny przykład z całą dzisiejszą składnią
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 } }
i tylko przykład użycia ...
switch side { case .left: textColor = .red case .right: textColor = .green }
W przypadku tej krytycznej kontroli jakości Swift / iOS
• bardzo stara odpowiedź @SwiftArchitect jest całkowicie poprawna, ale
• Właśnie zaktualizowałem go i dodałem krytyczną „niedostępną” rzecz, która jest teraz możliwa w Swift.
źródło
To stary wątek, ale przydatny. Dostosowałem moją odpowiedź do Swift 4.0 i Xcode 9.0 - Swift 4 ma własne małe problemy z tym problemem. Mam zmienną @IBInspectable z typem wyliczenia i Xcode 9.0 nie jest zadowolony, pokazując mi tę „Właściwość nie może być oznaczona jako @IBInspectable, ponieważ jej typ nie może być reprezentowany w Objective-c”
@Eporediese częściowo rozwiązuje ten problem (dla swift3); używając właściwości dla scenorysu, ale prostego wyliczenia dla pozostałej części kodu. Poniżej znajduje się bardziej kompletny zestaw kodów, który zawiera właściwość do pracy w obu przypadkach.
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
źródło
Rozwiązanie Swift 3 oparte na 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
źródło
#if TARGET_INTERFACE_BUILDER
bloku, wpłynie to tylko na renderowanie w programie Interface Builder, a nie w czasie wykonywania. Spowoduje to prawdopodobnie nieoczekiwane zachowanie i zawsze otrzymasz ostrzeżenie w konsoli:Failed to set (statusShapeIB) user defined inspected property ...: this class is not key value coding-compliant for the key statusShapeIB.