SwiftPackageManagerでxibファイルを使う
この記事は、「愛好会 開発合宿in沖縄に参加してきた(成果編) SPMベースのプロジェクトを作る」の記事の解説記事の1つです。
この記事では、SPMでxibファイルを使う方法をまとめました。
現在筆者がUIを作る時は、①SwiftUI or ②UIKitを使用して全てコードで作るが、現状会社のアプリにはxibやStoryboardも含まれているので、今回はPackage内でxibなどのInterfaceBuilder(以下、IB)のファイルを使う方法をまとめます。
今回もSPMProjectのリポジトリをサンプルとして利用します。
xibファイルはResource扱いになる
まず確認しなければいけないのは、xibなどのファイルはResource扱いになる、つまりBundleディレクトリに格納されるということです。
したがってそこの設定を間違えると、ただしくxibファイルがロードできないというトラブルが発生してしまいます。
この詳細は、WWDC2020のSwift packages: Resources and localizationの動画で説明されています。
上記の動画で説明があるように、PackageではResourcesディレクトリにリソースファイルは含める必要がありますが、xibやstoryboard, xcassetsなどファイルは自動でBundleにコピーされるので、どこに配置しても問題はありません。
逆にjsonやscriptファイルなど、他のファイルの場合はResourcesディレクトリに配置する必要があります。
xibファイルの実装方法
基本的な実装方法は同じですが、異なる点や注意点があるので、それらをまとめます。
ClassのModuleはPackage名にする
以下のxibのFile's Ownerの設定で、デフォルトはInherit Module From Targetに✅が入っていると思います。
しかしそのままだとxibがうまくロードできないので、✅を外して、Moduleの名前をそのxibが格納されているPackage名に変更しましょう

コードからxibをロードする時は、Bundle.moduleのBundleを指定する
実際にコードからxibをロードする時には、Bundleを指定すると思いますが、その時に例えばBundle.mainを指定しまうと、アプリのメインのTargetのBundleが指定されてしまい、格納されているBundleが異なるので、うまくロードできません。
そこでPackageでBundleを指定する場合は、Bundle.moduleを指定します。
このアプリではxibをロードするようのコードを以下のように共通化しています。
public extension UIView {
func loadNib(bundle: Bundle? = nil) {
let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle ?? Bundle(for: type(of: self)))
guard let view = nib.instantiate(withOwner: self, options: nil).first as? UIView else { return }
addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
view.topAnchor.constraint(equalTo: topAnchor),
view.leadingAnchor.constraint(equalTo: leadingAnchor),
trailingAnchor.constraint(equalTo: view.trailingAnchor),
bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
}この関数は引数にBundleを指定するようになっているので、使用する時に以下のように、.moduleを指定します
loadNib(bundle: .module)xibで画像を使用する時の注意点
今までマルチモジュール構成をする時は、1つのモジュールに画像などを集約するようにしていたが、xibの場合は他のモジュール(Bundle)の画像を表示することができません。
正確にはIB上では画像は選択することができて、表示もされるのですが、実際にアプリをビルドしてみると、その画像は表示されません。IBOutletで接続後に、コードで設定することもできますが、それではxibなどのIBを使うメリットが半減です。
これでは運用的にも微妙なので、別の解説記事に書いた通り、画像についてはPackageごとに管理するのが現時点ではよさそうです
ちなみにアセットの色はファイルは共通のPackageのものを利用することができます。