列挙型のIBInspectableを作成する方法


83

enumInterfaceBuilderで定義されたランタイム属性ではありません。以下は、InterfaceBuilderの属性インスペクターには表示されません。

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

ドキュメントから: IBInspectable属性は、クラス宣言、クラス拡張、またはInterface Builderで定義されたランタイム属性でサポートされている任意のタイプのカテゴリ(ブール値、整数または浮動小数点数、文字列、ローカライズされた文字列、長方形)の任意のプロパティに添付できます。 、ポイント、サイズ、色、範囲、およびなし。

Q:enum Interface Builderの属性インスペクターでを確認するにはどうすればよいですか?


1
そのリストの列挙型はどこにありますか?なぜ列挙型を使用できると思いますか?
Paulw11 2014

13
ネイティブのUIKitオブジェクトのように、enum私が思うIBから直接ケースを選択できるとUIFont便利です。
SwiftArchitect 2015年

回答:


76

スウィフト3

@IBInspectable var shape:StatusShape = .Rectangleは、InterfaceBuilderに空白のエントリを作成するだけです。

IBでは利用できません

SwiftとInterfaceBuilderの間のブリッジとして機能するアダプターを使用します。
shapeAdapterIBから検査可能です:

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

IBで利用可能

条件付きコンパイルアプローチ(を使用#if TARGET_INTERFACE_BUILDER)とは異なり、shape変数のタイプはターゲットによって変更されないため、shape:NSIntegervs。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計算されたプロパティではなく、保存されたプロパティとして保持するのはなぜですか?
nhgrif 2015年

正しい。writeonlyただし、プロパティを作成することはできません...ただし、計算されたプロパティは、保存されたプロパティのようにバッキングインスタンス変数を作成しません。
nhgrif 2015年

@nhgrifによって提案されたバッキングストアなしのソリューションを追加しました。
SwiftArchitect 2015年

1
すみません、反対票を投じてください。TARGET_INTERFACE_BUILDERで実用的な解決策があると思いましたが、誤解されました。申し訳ありませんが、ここSOで頑張ってください
Dan Rosenstark 2015年

2017年まで早送りすると、この問題は引き続き同じですか?
NoSixties 2017年

41

検査可能な列挙型をintで設定する代わりに、文字列で設定することもできます。ドロップダウンほど好ましくはありませんが、少なくともこのオプションはある程度の読みやすさを提供します。

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互換性のあるSwiftオプション:

@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
        }
    }
}

2
私はこのSwift Onlyバージョンが好きです:それはIBで平易な英語を可能にします
SwiftArchitect 2015

この方法を使用して、IBで文字列のドロップダウンとして表示されるオプションを取得する方法を知っている人はいますか?
airowe

ドロップダウンを使用してこれを行う方法を可能であれば知りたいのですが。
ワエル・

19

迅速な構文を思い出せませんが、これがobj-cで解決した方法です。

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

1
私が条件付きアセンブリを持っている唯一の場所は、宣言のその1つの場所です。列挙型はobj-cの整数値であるため、他の場所には条件付きアセンブリはありません。アップルがこれを修正するときに削除する1つの場所(修正すると仮定)
Jason Bobier 2015年

これは機知に富んだ素晴らしいソリューションであり、ここで言及されていますnshipster.com/ibinspectable-ibdesignable
Dan Rosenstark 2015年

7

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
    }

この重要なSwift / iOS QAの場合、

•@ SwiftArchitectの非常に古い答えは完全に正しいですが、

•私はそれを更新し、Swiftで可能になった重要な「利用できない」ものを追加しました。


4

これは古いスレッドですが、便利です。私は自分の答えをswift4.0とXcode9.0に適合させました-Swift4には、この問題に関して独自の小さな問題があります。列挙型の@IBInspectable変数があり、Xcode 9.0は満足できません。「プロパティは、Objective-cで表現できないため、@ IBInspectableとマークできません」と表示されます。

@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

2

スウィフト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

2
このIB-inspectableプロパティを#if TARGET_INTERFACE_BUILDERブロックでラップすると、実行時ではなく、InterfaceBuilderでのレンダリングにのみ影響します。これはおそらく予期しない動作になりますと、あなたは常にコンソールに警告取得します:Failed to set (statusShapeIB) user defined inspected property ...: this class is not key value coding-compliant for the key statusShapeIB.
ミーシャ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.