web-dev-qa-db-ja.com

列挙型で@IBInspectable?

次の図に示すように、@IBInspectable要素を作成したいと思います。

enter image description here

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

編集:

@IBInspectableはこれらのタイプのみをサポートしているようです:

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

残念

77
ignotusverum

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

Appleの doc から:

IBInspectable属性は、Interface Builderで定義された実行時属性でサポートされているタイプのクラス宣言、クラス拡張、またはカテゴリのプロパティに添付できます。ブール、整数または浮動小数点数、文字列、ローカライズされた文字列、長方形、ポイント、サイズ、色、範囲、およびnil。

25
yusuke024

これに対する別の回避策は、列挙プロパティがインターフェイスビルダーに表示される方法を変更することです。例えば:

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

これは、FontWeightという列挙型を前提としています。列挙型とその生の整数値は、Objective-Cで多少交換可能に使用できるという事実に依存しています。これを行った後、理想的ではないが機能し、同じプロパティをプログラムで使用するときに少量のタイプセーフを保持する整数を、Interface Builderでプロパティに指定できます。

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

ただし、これはSwiftでは機能しません。整数から列挙型に暗黙的にキャストすることができないためです。

21
Anthony Mattox

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

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

7
Matthew Cawley

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

インターフェイスビルドでは、文字列(enum値と同じ)を入力するだけで明確になります(数字を入力する場合、誰も意味を知らない)

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
        }

    }

}
1
HixField

enumの識別子は、Objective-Cの誰でも実行時に利用できないことを付け加えます。そのため、どこにでも表示することはできません。

1
Amin Negm-Awad

@sikhapolが答えたように、これは不可能です。これに使用する回避策は、クラスにIBInspectable boolsの束を持ち、インターフェイスビルダーで1つを選択することです。複数のセキュリティが設定されていないセキュリティを強化するには、各セキュリティのセッターにNSAssertを追加します。

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

これは少し面倒で少しだらしないIMOですが、この種の動作を実現する唯一の方法です。

1
Chris

私の解決策はそうすることでした:

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

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

1
Gal Marom