こんにちはiOS開発をしている福山です。
この記事では、SwiftGenとSwift-DocCを用いて、xcassetsを開かずにコード内の画像をQuick Help(右パネルまたは⌥オプションキー+クリック)で直接確認する方法を紹介します。
各ツールの簡単な説明
Swift-DocCは、Swift言語用のドキュメント生成ツールです。Swiftコード内に書かれたコメントから、ナビゲーションが容易で、見た目も美しいドキュメントを生成することができます。
SwiftGenは、Xcodeプロジェクトで使われるリソース(画像、フォント、色、ローカライズなど)を静的に型付けされたSwiftコードに変換するツールです。自動生成された安全なコードを通じてリソースにアクセスできるため、タイプミスによるエラーや存在しないリソースへの参照をコンパイル時に検出するのに役立ちます。
enum Asset { static let mirrabit1 = ImageAsset(name: "mirrabit1") static let mirrabit2 = ImageAsset(name: "mirrabit2") static let mirrabit3 = ImageAsset(name: "mirrabit3") }
imageView.image = Asset.mirrabit1.image
ただ、Swiftの定数から対象の画像を確認するには、いちいち元のxcassetsを開いて画像名を検索をするという無意識に時間を削る作業が発生していたため、なんとか対処します。
処理の流れ
- Xcode から .docc フォルダを作成
- SwiftGen の画像用設定
- xcassets から .docc フォルダへ画像を自動コピー
Xcode から.doccフォルダを作成
SwiftGenImageDocCという新しいプロジェクトを作成したところから始めます。使用しているXcodeは15.2です。
プロジェクトフォルダから New File... > Documentation Catalog で.doccフォルダを追加します。
.docc 内のResources内にCopyOfAssetsImagesというフォルダを追加します。 後の作業でCopyOfAssetsImagesにAssets.xcassetsの画像を自動でコピーすることでQuick Helpで画像を参照できるようになります。
開発時に使う機能なので、自動コピーした画像をgitで管理したくない場合は、 CopyOfAssetsXcassets内に.gitignoreを追加します。
$ touch SwiftGenImageDocC/Documentation.docc/Resources/CopyOfAssetsXcassets/.gitignore
*.jpeg *.jpg *.png
SwiftGenの画像用設定
既にあるAssets.xcassetsにいくつかの画像を準備します。
プロジェクトフォルダに SwiftGen フォルダとその中の Generated, Templates フォルダを作成します。 そして自動生成されたファイルを Xcode に参照させるため、Generated の中に Assets.swift を作成しておきます。
SwiftGenの標準テンプレートをTemplatesフォルダへ出力します。
swiftgenコマンドが入っていない場合は brew install swiftgen
などで導入します。
$ swiftgen template cat xcassets swift5 >SwiftGenImageDocC/SwiftGen/Templates/Assets.stencil
出力した SwiftGenImageDocC/SwiftGen/Templates/Assets.stencil の107行目あたり ({% elif asset.type == "image" %}
の後) に以下の1行追加します。
{% elif asset.type == "image" %}
+ /// ![xcassets image]({{asset.value}})
{{accessModifier}} static let {{asset.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{imageType}}(name: "{{asset.value}}")
{% elif asset.type == "symbol" %}
次にプロジェクトルートにswiftgen.ymlファイルを作成します。
$ touch swiftgen.yml
xcassets: - inputs: SwiftGenImageDocC/Assets.xcassets outputs: - templatePath: SwiftGenImageDocC/SwiftGen/Templates/Assets.stencil output: SwiftGenImageDocC/SwiftGen/Generated/Assets.swift params: publicAccess: false
xcassetsから.doccフォルダへ画像を自動コピー
スクリプトファイルを作成し、実行権限を付与します。
$ touch SwiftGenImageDocC/SwiftGen/copy-images-for-docc.sh $ chmod +x SwiftGenImageDocC/SwiftGen/copy-images-for-docc.sh
#!/bin/bash # Assets.xcassets の画像をSwift-DocC用フォルダへコピーするスクリプト copyAndRenameImages() { local xcassets_path="$1" local target_folder_path="$2" # 引数パスが指定されているか確認 if [[ -z "$xcassets_path" || -z "$target_folder_path" ]]; then echo "使用方法: copyAndRenameImages <xcassets_path> <target_folder_path>" return 1 fi # .imagesetフォルダを捜索 find "$xcassets_path" -name "*.imageset" -print0 | while IFS= read -r -d '' imageset; do imageset_name=$(basename "$imageset" .imageset) # .imagesetフォルダ内の画像を捜索 find "$imageset" -type f \( -name "*.png" -o -name "*.jpeg" -o -name "*.jpg" -o -name "*.svg" -o -name "*.pdf" \) -print0 | while IFS= read -r -d '' image; do base_name=$(basename "$image" | sed -E 's/(@[0-9]x)?\.(jpg|jpeg|png|svg|pdf)$//') # 拡張子を検出 ext="${image##*.}" # target_folder_pathへ画像を変換orコピー(高い解像度を優先) for res in "@3x" "@2x" ""; do file="$imageset/$base_name$res.$ext" if [[ -f "$file" ]]; then # Swift DocCで使えるように変換orコピー & 画像ファイル名を調整 if [[ "$ext" == "pdf" || "$ext" == "svg" ]]; then # pdf,svg画像はpngへ変換 sips -s format png "$file" --out "$target_folder_path/$imageset_name.png" else cp "$file" "$target_folder_path/$imageset_name.$ext" fi break 2 fi done done done } # パスを定義 xcassets_path="SwiftGenImageDocC/Assets.xcassets" target_folder_path="SwiftGenImageDocC/Documentation.docc/Resources/CopyOfAssetsXcassets" # target_folder_pathの存在とディレクトリかどうかを確認 if [[ -d "$target_folder_path" ]]; then if [[ "$(ls -A "$target_folder_path")" ]]; then # 隠しファイル(.gitignore等)以外の全てをtarget_folder_pathから削除 rm -rf "$target_folder_path"/* fi else echo "$target_folder_path は存在しない、あるいはディレクトリではありません" fi copyAndRenameImages $xcassets_path $target_folder_path
そして、スクリプトとswiftgenコマンドの呼び出しを簡略化するためにMakefileを作成します。
$ touch Makefile
swiftgen: SwiftGenImageDocC/SwiftGen/copy-images-for-docc.sh swiftgen
全ての準備が完了したので以下のコマンドを実行します。xcassetsに新しい画像を追加したときも、こちらのコマンドで更新可能です。
$ make swiftgen
SwiftGenImageDocC/Documentation.docc/Resources/CopyOfAssetsXcassets/
下に画像ファイルが入ればOKです。
今回の流れでファイル構成は以下のようになっているかと思います。 左: 別エディタ, 右: Xcode
ここまで来ると Asset.imageName.image
や Asset.imageName.swiftUIImage
の imageName
部分を ⌥オプション+クリック でポップアップが表示されるようになります。
表示されない場合は Xcode の再起動などを試すと出てくることがあります。今回使う機能ではメニューから Product > Build Documentation する必要はありません。
おわりに
最近は xcassets 以外にUIコンポーネントのスクショなどもQuick Helpで見られるようにしています。プロジェクトが大きくなるほど単純な表示の確認だけならXcode Previewsよりも早くサクッと確認できるので嬉しいです。
We are hiring!
ミラティブではMirrativをより良いプロダクトにし、「好きでつながり自分の物語が生まれる居場所」をつくるエンジニアを募集中です!