LoginSignup
14
7

More than 1 year has passed since last update.

SwiftGenのセットアップ方法&使い方(SwiftPM)

Last updated at Posted at 2023-01-17

はじめに

SwiftGenをSwiftPMで使う方法を紹介します。

「SwiftGen」とは?

リソース(ローカライズされた文字列や画像など)に対してSwiftのコードを生成し、型安全にアクセスするためのCLIツールです。
R.swiftと競合するパッケージです。

R.swiftとの比較

R.swiftとSwiftGenを比較します。
両方とも素晴らしいパッケージなので、どちらを使うか迷います。

  • CLIツールのみで完結する
    R.swiftはCLIツールとライブラリの両方が必要なのに対し、SwiftGenはCLIツールのみで完結する
  • 設定ファイルが必要
    R.swiftは設定ファイルが不要なのに対し、SwiftGenは作成する必要がある

個人的な感覚は以下の通りです。

  • 簡単に使いたい → R.swift
  • ライブラリを増やしたくない、またはカスタマイズしたい → SwiftGen

SwiftGen導入のメリット

R.swiftと同様なので、以下の記事をご参照ください。

環境

  • OS:macOS Monterey 12.5.1
  • Xcode:14.2 (14C18)
  • Swift:5.7.2
  • Swift Package Manager:5.7.1
  • SwiftGen:6.6.2

セットアップ方法

SwiftGenプラグインのインストール

SwiftGenは公式でプラグインが用意されています。
CLIツールとプラグインでリポジトリが分かれているのが特徴です。

プラグインはSwiftGenのArtifact bundle(≒ビルド済みバイナリ)にのみ依存していることが明確になっており、他のパッケージと依存が被らないので使いやすいです。

インストールは Package.swiftdependencies: に追記するのみです。

Package.swift
    dependencies: [
+       .package(url: "https://github.com/SwiftGen/SwiftGenPlugin", from: "6.6.2"),
    ],

ビルド時にリソースファイルを生成するようにする

Package.swift のリソースが含まれているターゲットにプラグインを追加するだけで、ビルド時に自動でリソースファイルが生成されます。

Package.swift
    targets: [
        .target(
            // ...
            plugins: [
+               .plugin(name: "SwiftGenPlugin", package: "SwiftGenPlugin"),
            ]),
    ]

リソースファイルを生成したい全ターゲットに追加する必要があります。

プラグインの追加が手間なので、リソース用のターゲット(モジュール)を作り、リソースを1つのモジュールで一元管理するのもありだと思います。
ただ私は今のところ、必要なリソースを必要なモジュールのみに含めるのが好みです。

設定ファイルを作成する

設定ファイルは各ターゲットのパスに swiftgen.yml を追加すると、自動的に読み込まれます。

以下は設定ファイルの一例です。

swiftgen.yml
input_dir: Resources
output_dir: ${DERIVED_SOURCES_DIR}

strings:
  inputs:
    - ja.lproj/Localizable.strings
  outputs:
      templateName: structured-swift5
      output: Strings.swift

xcassets:
  inputs:
    - Assets.xcassets
  outputs:
    templateName: swift5
    output: Assets.swift

Swift Package Manager 5.7.1時点で、Build Tool Pluginは DerivedData${DERIVED_SOURCES_DIR} ) にしかファイルを生成できません。
そのため output_dir は変更できません。

1つの設定ファイルに複数のターゲットの設定をまとめて書くこともできます。
私はターゲットを削除するときに設定を消し忘れるのを防ぐため、ターゲットごとに設定を書くのが好みです。

設定ファイルの書き方の詳細は、公式ドキュメントをご参照ください。

使い方

ローカライズされた文字列

structured-swift5 テンプレートを使う場合、 L10n.○○ でローカライズされた文字列にアクセスできます。

- String(localized: "Copy Sakatsu text", bundle: .module)
+ L10n.copySakatsuText

アセット

swift5 テンプレートを使う場合、 Asset.○○.image で画像に UIImage としてアクセスできます。

- Image("foo_and_bar", bundle: .module)
+ Image(uiImage: Asset.fooAndBar.image)

Asset.○○.swiftUIImageSwiftUI.Image としてアクセスできるので、SwiftUIの場合はこちらのほうがスマートです。

- Image(uiImage: Asset.fooAndBar.image)
+ Asset.fooAndBar.swiftUIImage

おまけ: プラグインを自作する

ソースを見ればわかりますが、プラグインはCLIツールをラップした薄いファイルです。

Build Tool Pluginの場合、CLIツールに引数を一切渡せないため、カスタマイズしたい場合はプラグインを自作する必要があります。

SwiftGenはArtifact bundleを提供しており、プラグインも100行ないため、簡単に自作できます。
プラグインを自作する方法は、以下の記事がわかりやすいです。

おまけ: マルチモジュールにおけるリソースの管理方法

SwiftPMでモジュール分割するとき、リソースをどう管理するかの考えを、以下のツイートのツリーでまとめています。

リソースを1つのモジュールで一元管理する場合、アクセス修飾子を internal から public にする必要があります。
swiftgen.yml から簡単に変更できます。

swiftgen.yml
input_dir: Resources
output_dir: ${DERIVED_SOURCES_DIR}

strings:
  inputs:
    - ja.lproj/Localizable.strings
  outputs:
    templateName: structured-swift5
    output: Strings.swift
+   params:
+     publicAccess: true

xcassets:
  inputs:
    - Assets.xcassets
  outputs:
    templateName: swift5
    output: Assets.swift
+   params:
+     publicAccess: true

おわりに

Swift Package上で、ローカライズされた文字列をスッキリかつ安全にアクセスできるようになりました :relaxed:
SwiftPMのプラグインは便利なので、他のCLIツールでも積極的に使っていきたいです。

参考リンク

14
7
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
14
7