はじめに
新規にXcode Projectを作成する時どのような構成が有利なのでしょうか。特に複数のメンバーでProjectを共有して開発するときにはXcode Project自体のコンフリクトが問題になることがありました。
Embedded Framework
Embedded Frameworkは、iOS8で導入された、動的フレームワークで、アプリの構造を分割して構成するための仕組みとなります。
アプリをモノリシックに作る場合は、全く関係ない話になります。
たとえば、ライブラリーを作成して別のプロジェクトで使いまわしたり、Clean Architectureなどを採用したい場合は、Embedded Frameworkを使った方が、疎結合が明確になり、テスタビリティを向上させ、不具合が低減すると思います。
コーディングに現れる特徴としては、
import EmbeddedFrameworkName
としてアクセスを宣言する必要が出てきます。
iOS界隈の言葉で言うと、「Bundleが異なる」ということになります。
実際「Bundle Identifier」はメインアプリとは異なる文字列になります。
便利なのですが、この方法ではprojectのコンフリクトは避けられませんでした。
ちなみにEmbed Frameworkではないようです。読みにくいですが文法的にもEmbedded Frameworkがただしいですね。
SPMの登場
Embedded Frameworkは、2014年に登場したわけですが、そのわずか2年後の2016年に SPM(Swift Package Manager)が登場します。
SPMは、ライブラリやツールの依存関係管理ツールであり、GitHub などからライブラリを取得してプロジェクトに組み込む用途で使われています。
ただ、SPMはネットワークから取得することは必須ではなく、ローカルに置いても利用可能で、自分のプロジェクト内にいても構いません。
また、Xcodeプロジェクトで管理した場合、Xcodeのファイル管理(XMLで記述されている)から外れているために、開発プロセスに於いてXcodeプロジェクト自体のコンフリクトが緩和されると言う大きなメリットがありました。Embedded Frameworkは、Xcodeがファイル管理しているため、盛大にコンフリクトが発生する可能性があります。
SPMマルチモジュールプロジェクトの登場
上記のSPMの特徴をXcodeのプロジェクト自体の基本構成に取り込み、
- アプリの分割構成
- Xcodeプロジェクトのコンフリクト緩和
を両立した手法が「SMPマルチモジュールプロジェクト」です。
Xcodeプロジェクトをメインバンドルである @Main 部分を残して(基本的に)全てSPMに分割してしまいます。
ただし、問題点として
- ビルドがかなり遅くなる
- SPMの差分ビルドにバグがあるようで、毎回clean buildしないと前回のキャッシュでビルドしてしまう
などがありました。要するにビルドが遅い!!と言うことです。
Xcode16登場
ところが、2024年に発表されたXcode16は、基本的にファイル管理がSPMライクになっており、フォルダの中のファイルをビルド対象として個別に登録するのではなく、フォルダにあるファイルが全てビルド対象になるような仕様変更が入ったようです。
プロジェクトナビゲータで「Convert to Folder(フォルダーに変換)」というコンテキストメニュー項目を使って、既存のグループをビルド可能なフォルダーに変換します。
ビルド可能なフォルダーは、含まれるファイルを列挙せずに、フォルダーパスだけをプロジェクトファイルに記録します。これにより、ファイルが追加・削除された際のプロジェクトへの差分が最小化され、チームでのソース管理における競合を回避できます。
つまり、SPMと同じく
- Xcodeプロジェクトのコンフリクト緩和
がXcodeの基本機能として実現されたのです。(みなさん、気づいていましたか?)
Xcode 16からビルド対象をGroupからFolder構成に変換するメニューができてる
yimajoさんの記事は、今の今まで気づいていませんでした・・・
私はXcodeを何となく使っていて発見しました。
Embedded Frameworkの復活
となれば、SPMと比較してビルドが非常に高速な(と言うか普通の)Embedded Frameworkを使ったプロジェクト構成が俄然注目されるべきじゃないでしょうか。
- アプリの分割構成が可能
- Xcodeプロジェクトのコンフリクト緩和
- ビルド速度が変わらない
Embedded Frameworkの落とし穴
ライブラリとは違い、Xcodeプロジェクトのレイヤー構造を構築するためにEmbedded Frameworkを使う場合は、注意すべきポイントがあります。
それは、複数のEmbedded Frameworkがお互いに参照する(importする)パターンが発生することです。
もちろんクロス参照はできないのですが、たとえばドメイン層のEmbedded Frameworkが、Tools層のEmbedded Frameworkを参照することはありそうです。
このためには、Xcodeで参照する側のTARGETを選び、importしたいEmbedded フレームワークを取り込む必要があります。(図1参照)
この時、importしたいEmbedded フレームワークを別のTARGETも取り込んでいるとどうなるでしょうか?
- Debugビルドはできる
- Debugアプリの起動はできる
- ❌ArchiveしてDistributionできない(図1参照)
です。
ビルドしてシミュレータや実機で動作しているのに、AppStoreConnectへアップロードできない!!
これは以前のEmbedded Frameworkからあった問題かもしれませんが、自分は記憶が飛んでいてかなり困りました。
ちなみに、Embedded Frameworkだけでなくメインアプリもimportしている場合は同じくエラーになります。
問題はこちらです。二つの赤枠がありますが、上の方は問題ありません。というか、ないとクラッシュします。
下の赤枠はビルド時にEmbedded FrameworkのバイナリーをiPhoneにコピーするため、それぞれのEmbedded Frameworkが同じ参照先のEmbedded Frameworkをコピーしていると、上記のエラーが発生することになります。
対策
対策は、下の赤枠のEmbedded Frameworkを削除し、アプリで1つだけコピーを許すようにXcodeを編集していくことです。
これはSPMだと考えなくて良かった落とし穴ですね。
ただ、Xcodeプロジェクト構造構築は、何度もやるものではなく、他のメリットが大きいため、Embedded Frameworkを使ったXcodeプロジェクトは選択肢としてはかなり良いのではないかと思っています。
まとめ
Frameworkを使ったXcodeプロジェクトは、
- アプリの分割構成が可能
- Xcodeプロジェクトのコンフリクト緩和
- ビルド速度が変わらない
- ただしArchive時のエラーに注意!
です。


