post Image
IBDesignableがウザい

機能自体は良いが色々とウザい。
簡単なViewを作るのに2、3時間費やしてしまったのでメモをアップする。

  • InterfaceBuilder(以降IB)表示時にビルドがかかり非常に重くなる
  • 普通のViewでは不要な考慮が色々必要
  • IB上でエラーが起きても原因が分かりづらい
  • IB上でエラーが起きるとXcodeがおかしくなることがある

IBを開くびにビルドがかかる

IBDesignableを修正してIBを開くとビルドがかかる。
IB上でフォントサイズを変えるだけでビルドがかかる。

メニューの “Editor” > “Automatically Refresh Views” のチェックを外すと自動でビルドがかからなくなる。
IB上で手動でViewをリフレッシュしたい場合、メニューの “Editor” > “Refresh All Views” を実行。

画像リソースを使えない

#imageLiteral で画像を参照するとIB上でクラッシュする。
UIImage(named: "xxxxx”) の形でUIImageを作ってもIB上では画像が表示されない。

IBDesignableでプログラムから画像を指定する場合、Bundleを動的に作って指定してやる必要がある。

let bundle = Bundle(for: type(of: self))
let image = UIImage(named: "pulldown_arrow", in: bundle, compatibleWith: nil)

エラーの原因が分かりづらい

エラーが出た場合、とりあえずIB上で問題のViewを選択して、メニューの “Editor” > “Debug Selected Views” を実行。
すると問題のViewがデバッガー付きで実行されるので、エラー箇所で停止してエラーの原因を確認することができる。

init で色などを設定してもIB上に反映されない

init でbackgroundColorなどを設定しても、initが実行された後にIBで設定された色に上書きされてしまいIB上では反映されない。(通常起動なら反映される)

ダメな例
class RedView: UIView {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    func setup() {
        backgroundColor = UIColor.red
    }
}

これを回避するには IB の設定が終わった後に、色などの設定を行う必要がある。
IBの設定時に prepareForInterfaceBuilder が呼ばれるので、これをoverrideして対応することができる。

いける例
class RedView: UIView {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        setup()
    }

    func setup() {
        backgroundColor = UIColor.red
    }
}

ただし、prepareForInterfaceBuilder は通常の実行時は呼ばれないので、init でも同じ設定をする必要がある。


『 Swift 』Article List