@IBInspectable
下の写真のように要素を作成したいと思います。
私のアイデアは、列挙型のようなものを型として使用することです@IBInspectable
が、そうではないようです。このような要素を実装する方法はありますか?
編集:
それはのように見える@IBInspectable
だけで、これらのタイプをサポート:
Int
CGFloat
Double
String
Bool
CGPoint
CGSize
CGRect
UIColor
UIImage
残念
@IBInspectable
下の写真のように要素を作成したいと思います。
私のアイデアは、列挙型のようなものを型として使用することです@IBInspectable
が、そうではないようです。このような要素を実装する方法はありますか?
編集:
それはのように見える@IBInspectable
だけで、これらのタイプをサポート:
Int
CGFloat
Double
String
Bool
CGPoint
CGSize
CGRect
UIColor
UIImage
残念
回答:
それは不可能です(今のところ)。「ユーザー定義のランタイム属性」セクションに表示されているタイプのみを使用できます。
Appleのドキュメントから:
IBInspectable属性は、クラス宣言、クラス拡張、またはInterface Builderで定義されたランタイム属性でサポートされている任意のタイプのカテゴリ(ブール値、整数または浮動小数点数、文字列、ローカライズされた文字列、長方形、ポイント、サイズ)の任意のプロパティにアタッチできます。 、色、範囲、およびなし。
これに対する別の回避策は、列挙型プロパティが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では機能しません。それを解決することについての考えはありがたいです。
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;
}
オプションで、そこにロジックを追加して、有効な値に設定されていることを確認できます。
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
}
}
}
@sikhapolが答えたように、これは不可能です。私がこれに使用する回避策IBInspectable
は、クラスにたくさんのboolを用意し、InterfaceBuilderで1つを選択することです。複数のものが設定されていないというセキュリティを強化するNSAssert
には、それぞれのセッターにを追加します。
- (void)setSomeBool:(BOOL)flag
{
if (flag)
{
NSAssert(!_someOtherFlag && !_someThirdFlag, @"Only one flag can be set");
}
}
これは少し退屈で少しずさんなIMOですが、私が考えることができるこの種の動作を実現する唯一の方法です
の識別子は、enum
Objective-Cの誰もが実行時に利用できないことを付け加えたいと思います。したがって、どこにでも表示することはできません。