Xcode 6からインタフェースビルダ (ストーリーボード) 向けに2つの修飾子@IBDesignable
と@IBInspectable
が追加されました。
この2つを使うことでストーリーボード上で実際に描画されたビューを見たり、ビューの属性を変更したりできるようになるので、試してみました。
なお、WWDC 2014のセッション「What’s new in Xcode 6」内の解説が詳しいです。
簡単な紹介
とりあえず使ってみましょう。
UIView
を継承したクラスを作成して、それに@IBDesignable
を付けます。
また、インスタンス属性を作成して、それには@IBInspectable
を付けます。
@IBDesignable class ShapeView: UIView { @IBInspectable var cornerRadius: CGFloat { get { return self.layer.cornerRadius } set { self.layer.cornerRadius = newValue } } @IBInspectable var shapeBackgroundColor: UIColor? { get { return UIColor(CGColor: self.layer.backgroundColor) } set { self.layer.backgroundColor = newValue?.CGColor } } }
次に、UIViewをストーリーボードに貼り付けてから、そのCustom ClassをShapeView
にします。
すると、Desinablesという項目が出現して、その値が「Up to date」になります。Up to dateは最新のコードと同じ表示がなされているということを意味しています。
Attributesインスペクタに移動すると@IBInspectable
で指定したプロパティが出現しています。
ここの値を変更すると、ストーリーボード上での表示もすぐに反映されます。
注意事項
現在のところ、@IBDesignable
と@IBInspectable
には次のような制限があるみたいです。
@IBDesignable
になるには、UIView
かNSView
の直接のサブクラスである必要がある (UITableViewCellを@IBDesignable
にしても表示されない)。@IBInspectable
になれる型はUser Defined Runtime Attributesと同じ。enum
は利用できない。- 画像などを表示する必要があって、とりあえずプレースホルダを設定させたいときなどは
prepareForInterfaceBuilder
を使うことができる (後の例では利用しています) - WWDCではウィジェット用のフレームワークを作る必要があるように言っているが、少なくともSwiftでは不要っぽい
なお、@IBInspectable
で設定した値は、IdentityインスペクタのUser Defined Runtime Attributesにも表示されるようになります。
なので、実は@IBInspectable
はUser Defined Runtime Attributesよりちょっと楽に値が設定できるだけだったりします。
ウィジェットのデバッグ
- そのウィジェットのブレークポイントを設置
- ウィジェットのストーリーボード上で選択
- メニューから、Edit → Debug Selected Views
複雑な例
サブビューがあっても@IBDesignable
が有効かどうかを試してみました。
@IBDesignable class EditTableViewCell: UIView { let titleLabel = UILabel() let textField = UITextField() @IBInspectable var title: String { get { return titleLabel.text! } set { titleLabel.text = newValue } } @IBInspectable var placeholder: String? { get { return textField.placeholder } set { textField.placeholder = newValue } } override init(frame: CGRect) { super.init(frame: frame) setupView() } override func prepareForInterfaceBuilder() { if titleLabel.text == nil { title = "titleを入力してください" } if textField.placeholder == nil { placeholder = "placeholderを入力してください" } } private func setupView() { addSubview(titleLabel) addSubview(textField) titleLabel.setTranslatesAutoresizingMaskIntoConstraints(false) textField.setTranslatesAutoresizingMaskIntoConstraints(false) addConstraints(layoutConstraints()) } }
試しにテーブルビューの静的表示でセルに貼り付けてみました。プロパティに値をセットしていないので、prepareForInterfaceBuilder
で指定した値が表示されています。
関連リンク
紹介したコードは次のリポジトリに上げています。
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。