@IBInspectable with enum?


87

@IBInspectable下の写真のように要素を作成したいと思います。

ここに画像の説明を入力してください

私のアイデアは、列挙型のようなものを型として使用することです@IBInspectableが、そうではないようです。このような要素を実装する方法はありますか?

編集:

それはのように見える@IBInspectableだけで、これらのタイプをサポート:

  • Int
  • CGFloat
  • Double
  • String
  • Bool
  • CGPoint
  • CGSize
  • CGRect
  • UIColor
  • UIImage

残念


ある種の回避策は、設定する値の前に検査可能な計算プロパティを配置することです。もちろん、InterfaceBuilderで列挙された値のポップアップメニューとして魔法のように表示されることはありません。ただし、少なくとも、検査可能な値を定義し、それを使用して列挙型を設定することができます。
マット2015

8
今年のWWDCで、私はDeveloperToolsラボのAppleエンジニアにこれについて尋ねました。彼はそれが素晴らしい機能になることに同意したと言ったが、それは現在不可能である。彼は私が行ったbugreport.apple.comでレーダーを提出することを提案しました。問題15505220の複製としてクローズされましたが、同様の問題を提起することを強くお勧めします。十分な数の人々が不満を言う場合、これらのことはしばしば対処されます。
クラーク



そして、SwiftUIとXcode 11の新しいCanvasを使用すると、これはAppleのロードマップには決して含まれないようです
BenLeggiero19年

回答:


27

それは不可能です(今のところ)。「ユーザー定義のランタイム属性」セクションに表示されているタイプのみを使用できます。

Appleのドキュメントから:

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


2
列挙型を使用する場合は、列挙型の値に明示的な割り当て(= 1、= 2など)を割り当てます。また、ハンドラーで、IBの値が列挙型の値の1つでない場合は、アサーションを追加します。列挙型がサポートされていないのは面倒ですが、このトリックにより、少なくとも列挙型がより使いやすくなります。
Zev Eisenberg

列挙型は整数です。
Amin Negm-Awad 2015

23

これに対する別の回避策は、列挙型プロパティがInterfaceBuilderにどのように表示されるかを変更することです。例えば:

#if TARGET_INTERFACE_BUILDER
@property (nonatomic, assign) IBInspectable NSInteger fontWeight;
#else
@property (nonatomic, assign) FontWeight fontWeight;
#endif

これは、FontWeightと呼ばれる列挙型を想定しています。これは、列挙型とその生の整数値をObjective-Cである程度互換的に使用できるという事実に依存しています。これを行った後、Interface Builderでプロパティの整数を指定できます。これは理想的ではありませんが、機能し、同じプロパティをプログラムで使用するときに少量の型安全性を保持します。

これは、別の整数プロパティを宣言するよりも優れた代替手段です。これは、同じことを実行するためにも使用できる2番目の整数プロパティを処理するために追加のロジックを記述する必要がないためです。

ただし、整数から列挙型に暗黙的にキャストすることはできないため、これはSwiftでは機能しません。それを解決することについての考えはありがたいです。


2
私はこれがSwiftで機能すると本当に思っていましたが、さらにテストを行うと...いいえ
Dan Rosenstark 2015年

7

Inspectable NSInteger値を使用してこれを行い、セッターをオーバーライドして列挙型を設定できるようにします。これには、ポップアップリストを使用しないという制限があり、列挙値を変更すると、インターフェイスオプションが一致するように更新されません。

例。

ヘッダーファイル内:

typedef NS_ENUM(NSInteger, LabelStyle)
{
    LabelStyleContent = 0, //Default to content label
    LabelStyleHeader,
};

...

@property LabelStyle labelStyle;
@property (nonatomic, setter=setLabelAsInt:) IBInspectable NSInteger labelStyleLink;

実装ファイル内:

- (void)setLabelAsInt:(NSInteger)value
{
    self.labelStyle = (LabelStyle)value;
}

オプションで、そこにロジックを追加して、有効な値に設定されていることを確認できます。


なぜこれが反対票を投じられたのかわからない。問題を回避するための良い方法のようです。
フォグマイスター2015年

ありがとう@ Fogmeister-私は現在、アプリ内でこの実装を実際に使用しています:)
Matthew Cawley 2015

4

Sikhapolは正しく、列挙型はxCode 9でもまだサポートされていません。最も安全なアプローチは、列挙型を文字列として使用し、「シャドウ」(プライベート)IBInspectable変数を実装することだと思います。これは、Interface Builder(swift 4)内でカスタムアイコン(PaintCodeを使用して実行)でスタイルを設定できるバーボタンアイテムを表すBarBtnPaintCodeアイテムの例です。

インターフェイスビルドでは、文字列(列挙値と同じ)を入力するだけで、文字列が明確になります(数値を入力している場合、その意味が誰にもわかりません)

class BarBtnPaintCode: BarBtnPaintCodeBase {

    enum TypeOfButton: String {
        case cancel
        case ok
        case done
        case edit
        case scanQr
        //values used for tracking if wrong input is used
        case uninitializedLoadedFromStoryboard
        case unknown
    }

    var typeOfButton = TypeOfButton.uninitializedLoadedFromStoryboard

    @IBInspectable private var type : String {
        set {
            typeOfButton = TypeOfButton(rawValue: newValue) ?? .unknown
            setup()
        }
        get {
            return typeOfButton.rawValue
        }
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    init(typeOfButton: TypeOfButton, title: String? = nil, target: AnyObject?, action: Selector) {
        super.init()
        self.typeOfButton = typeOfButton
        setup()
        self.target = target
        self.action = action
        self.title  = title
    }

    override func setup() {
        //same for all
        setTitleTextAttributes([NSAttributedStringKey.font : UIFont.defaultFont(size: 15)],for: UIControlState.normal)
        //depending on the type
        switch typeOfButton {
        case .cancel  :
            title = nil
            image = PaintCode.imageOfBarbtn_cancel(language: currentVisibleLanguage)
        case .ok      :
            title = nil
            image = PaintCode.imageOfBarbtn_ok(language: currentVisibleLanguage)
        case .done    :
            title = nil
            image = PaintCode.imageOfBarbtn_done(language: currentVisibleLanguage)
        case .edit    :
            title = nil
            image = PaintCode.imageOfBarbtn_edit(language: currentVisibleLanguage)
        case .uninitializedLoadedFromStoryboard :
            title = nil
            image = PaintCode.imageOfBarbtn_unknown
            break
        case .unknown:
            log.error("BarBtnPaintCode used with unrecognized type")
            title = nil
            image = PaintCode.imageOfBarbtn_unknown
            break
        }

    }

}

Swift4で実装された素晴らしいソリューションは問題ありません。これを使用する場合は、ストーリーボードとxibのスペルタイプに注意してください
MindBlower3 2018

1

@sikhapolが答えたように、これは不可能です。私がこれに使用する回避策IBInspectableは、クラスにたくさんのboolを用意し、InterfaceBuilderで1つを選択することです。複数のものが設定されていないというセキュリティを強化するNSAssertには、それぞれのセッターにを追加します。

- (void)setSomeBool:(BOOL)flag
{
    if (flag)
    {
        NSAssert(!_someOtherFlag && !_someThirdFlag, @"Only one flag can be set");
    }
}

これは少し退屈で少しずさんなIMOですが、私が考えることができるこの種の動作を実現する唯一の方法です


1

の識別子は、enumObjective-Cの誰もが実行時に利用できないことを付け加えたいと思います。したがって、どこにでも表示することはできません。


1

私の解決策は次のことでした:

@IBInspectable  
var keyboardType = UIKeyboardType.default.rawValue {
        didSet { 
             textField.keyboardType = UIKeyboardType(rawValue: keyboardType)! 
        }
}

IB自体では、keyboardTypeフィールドにintを設定する必要があります

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.