1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SwiftPackageでマルチモジュール開発

Last updated at Posted at 2023-05-17

今回はマルチモジュール開発の話。
最近のSwiftPackageを使ったマルチモジュール開発について調査しました。

はじめに

開発が大きくなったり複数人で進めていく場合、モジュール分割してないとよくわからない状態でも実装を進められてしまいます。最初はなんとなく動作しているのでうまく実装できているような気になりますが、その状態で進めると依存関係がどんどん複雑になり、不具合が多くなってしまう原因になります。

モジュールを分割することで、

  • ある程度の実装方法を強制できる
  • モジュール単位での依存関係が把握できる
  • 関心のあるモジュールのみ把握すればいい 等

以上のメリットがあり、開発しやすくなります。

プロジェクトでモジュール分割

musicLineでは複数のプロジェクトを作成して、マルチモジュール開発を実現してました。
しかし、プロジェクト設定で依存関係やライブラリの種類を設定することが大変でした。

SwiftPackageでモジュール分割

以前よりもモジュール分割を細分化し、SwiftPackageでモジュール分割した結果です。

SwiftPackageを使用することで、フォルダ階層を分けるだけでモジュールを分割できました。
以前までのプロジェクト設定等の煩わしい作業がなくなり、スッキリしました。


ソースコード等の詳細はこちら

ポイント

1. フォルダを階層化したい

パッケージ設定で.targetによりターゲットを作成すると、デフォルトはSourcesの直下のフォルダを参照しますが、pathラベルよりフォルダのパスを設定できます。

例えば、CoreModelの場合

.target(
    name: "CoreModel",
    path: "Sources/01.Core/CoreModel")

Package.swiftファイルから相対パスで指定します。

2. モジュールにリソースを含める

モジュールにリソースを含める場合、resourcesラベルでリソースリストを指定します。
リソースは以下の2種類あり、モジュールフォルダからの相対パスを指定して作成します。

  • .process
    フォルダ階層を除去して、Bundle直下にファイルをコピーする
  • .copy
    フォルダ階層そのままで、フォルダごとコピーする

例えば、Commonモジュール直下のdataフォルダをリソースに追加したい場合、以下のように設定します。

.testTarget(
    name: "CommonTests",
    dependencies: ["Common"],
    resources: [.process("data")]
)

また、プロジェクトからモジュールに移行するときに、参照するBundleに注意です。

// プロジェクトの場合
Bundle(for: type(of: self))

// モジュールの場合
Bundle.module

3. なぜかAssetsからリソースを取得できない

Assetsでリソースを登録しているのに、SwiftUIのColorやImageがリソースから取得できない状態になっていました。
原因は異なるBundleを参照しており、Assets内のリソースに指定したリソースが無いため、取得できていませんでした。特にどこのBundleを参照しているかを意識していなかったのですが、デフォルトではメイン(現在実行中のコードを含むBundle)を参照するようで、モジュールのBundleを参照することで解決しました。

// プロジェクトの場合
Color("color_name")

// モジュールの場合
Color("color_name", bundle: .module)

4. リリース時にPreview Contentフォルダを除外したい

プロジェクトみたいにDevelopment Assetsに登録して、リリース時にフォルダを除外するような挙動はできないようで困りました。
excludeラベルで一部のフォルダを除外できるようですが、デバッグ時には欲しいファイルなのでこれは使えず。。
最終的にはターゲットを新しく作成して、ライブラリを別にすることでこの問題を回避しました。でもこの方法だと、スキームが無駄に多くなってしまうことが気になるところです。

Previewする時のクラスはファイルに書き出さずに、Viewファイルの中でPreviewProviderクラスと一緒に#if DEBUGで定義した方がスマートかもしれません。
いい方法があればコメントください。。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?