enum
это не является Интерфейс Builder атрибута определяется во время выполнения. Следующее не отображается в инспекторе атрибутов Interface Builder:
enum StatusShape:Int {
case Rectangle = 0
case Triangle = 1
case Circle = 2
}
@IBInspectable var shape:StatusShape = .Rectangle
Из документации: Вы можете прикрепить атрибут IBInspectable к любому свойству в объявлении класса, расширении класса или категории для любого типа, который поддерживается определенными атрибутами времени выполнения Interface Builder: логическое, целое число или число с плавающей запятой, строка, локализованная строка, прямоугольник , точка, размер, цвет, диапазон и ноль.
В: Как я могу увидеть enum
инспектор атрибутов в Интерфейсном Разработчике?
ios
xcode
swift
interface-builder
SwiftАрхитектор
источник
источник
enum
случай прямо из IB, я полагаю, илиUIFont
, как это могут делать собственные объекты UIKit.Ответы:
Swift 3
@IBInspectable
var shape:StatusShape = .Rectangle
просто создает пустую запись в Интерфейсном Разработчике :Используйте адаптер, который будет действовать как мост между Swift и Interface Builder.
shapeAdapter
проверяется из ИБ:// IB: use the adapter @IBInspectable var shapeAdapter:Int { get { return self.shape.rawValue } set( shapeIndex) { self.shape = StatusShape(rawValue: shapeIndex) ?? .Rectangle } }
В отличие от подхода с условной компиляцией (с использованием
#if TARGET_INTERFACE_BUILDER
), типshape
переменной не меняется в зависимости от цели, что потенциально требует дополнительных изменений исходного кода, чтобы справиться с вариантамиshape:NSInteger
vs.shape:StatusShape
// Programmatically: use the enum var shape:StatusShape = .Rectangle
Полный код
@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 } } }
► Найдите это решение на GitHub .
источник
shapeAsInt
храните свойство, а не вычисляемое?writeonly
... но вычисленное свойство не создает переменную резервного экземпляра, как это делает ваше сохраненное свойство.Вместо того, чтобы устанавливать проверяемые перечисления с помощью целых чисел, вы также можете установить их с помощью строк. Хотя это не так предпочтительно, как раскрывающийся список, по крайней мере, этот вариант обеспечивает некоторый уровень читабельности.
Вариант только для 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 } } }
Это является возможным также получить эту работу с Objective-C , а также путем добавления инициализатора в перечисление. Однако компилятор покажет только ошибку «недоступен» для ваших свойств только для IB в быстром коде.
Быстрый вариант с совместимостью с 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 } } }
источник
Swift Only
вариант: он позволяет без обиняков в IB .Я не могу вспомнить быстрый синтаксис, но вот как я решил его в obj-c
#if TARGET_INTERFACE_BUILDER @property (nonatomic) IBInspectable NSInteger shape; #else @property (nonatomic) StatusShape shape; #endif
источник
На 2020 год - ответ @SwiftArchitect обновлен на сегодня:
Вот типичный полный пример со всем сегодняшним синтаксисом
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 } }
и просто пример использования ...
switch side { case .left: textColor = .red case .right: textColor = .green }
Для этого критически важного QA Swift / iOS,
• очень старый ответ @SwiftArchitect совершенно правильный, но
• Я только что обновил его и добавил критическую «недоступность», что теперь возможно в Swift.
источник
Это старая ветка, но полезная. Я адаптировал свой ответ для Swift 4.0 и Xcode 9.0 - Swift 4 имеет свои небольшие проблемы с этой проблемой. У меня есть переменная @IBInspectable с типом перечисления, и Xcode 9.0 не доволен, показывая мне это «Свойство нельзя пометить @IBInspectable, потому что его тип не может быть представлен в Objective-c»
@Eporediese частично отвечает на эту проблему (для swift3); используя свойство для раскадровки, но прямое перечисление для остальной части кода. Ниже приведен более полный набор кодов, который дает вам свойство, с которым можно работать в обоих случаях.
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
источник
Решение Swift 3 на основе 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
источник
#if TARGET_INTERFACE_BUILDER
блок, это повлияет только на рендеринг в Интерфейсном Разработчике, но не во время выполнения. Скорее всего, это приведет к неожиданному поведению, и вы всегда будете получать предупреждение в консоли:Failed to set (statusShapeIB) user defined inspected property ...: this class is not key value coding-compliant for the key statusShapeIB.