🐾

xibと紐付けたUIViewをViewControllerで使う時の罠

2023/05/21に公開

前提

xibのインスタンス化する方法はいくつかありますが、下記を想定しています。

  1. UIViewを継承したHogeViewを作る
  2. HogeViewとHogeView.xibを紐づける(xibのfile's ownerにHogeViewを指定する)
  3. HogeViewでHogeView.xibをロードする
init() {
    super.init(frame: .zero)
    
    let view = UINib(nibName: "CustomView", bundle: nil)
        .instantiate(withOwner: self).first as! UIView
    view.frame = bounds
    view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    addSubview(view)
}
  1. HogeViewをHogeViewControllerでインスタンス化し、表示する

注意点

ViewControllerはloadView()で関連するnibファイルを勝手にロードするみたいです。
ソース

関連するnibファイルとは

  • クラス名から「Controller」という単語を取り除いたファイル
    • 例: CustomViewControllerはCustomView.nib(xib)を探す
  • クラス名と同じファイル
    • 例: CustomViewControllerはCustomViewController.nib(xib)を探す

ソース

前提を確認すると、HogeViewControllerはHogeView.xibをロードしてしまうことが分かります。
(この場合、xibファイルが見つからない旨のエラーでクラッシュします)

解決策

loadView()をoverrideする

class CustomViewController: UIViewController {
    
    private let customView = CustomView()
    
    override func loadView() {
        super.loadView()
        view = customView
    }
}

最後に

勝手にロードする仕様が若干解せないですが、xibをViewControllerに直接紐づける場合は役立ちますね。
最後まで読んでいただき、ありがとうございました。

GitHubで編集を提案

Discussion