All Articles

XcodeGenを使ったプロジェクト作成

はじめに

iOS アプリは、*.xcodeproj (以降プロジェクト管理ファイルと呼ぶ)でプロジェクトファイルを管理しています。

この*.xcodeprojの中には、project.pbxproj というテキストファイルが存在しますが、 プロジェクトファイルの管理、ライブラリの管理、ファイルの並び順を管理しているため、 ファイルサイズがとても大きくなり編集が難しくなります。

*.xcodeproj の管理の課題

  • コンフリクト解消がつらい。
  • 編集をミスすると iOS アプリプロジェクトが開かなくなる。
  • レビューがしづらい。← ファイルを並び順を変えるだけで大きな差分が発生します。チーム開発時は気持ち悪いと思いながらファイル名を並び替えるのを見送っていました。

XcodeGen とは

XcodeGen とは、YAML(project.yml)から、*.xcodeproj を生成できるユーティリティです。

メリット

  • 同一の project.yml からは、何度実行しても同じ*.xcodeprojが作成されます。(冪等性)
  • プロジェクトのファイルが名前順に自動ソートされます。
  • レビューが可能です。

デメリット

  • project.yml に慣れる必要があります。
  • 既存の大きな PJ からの移行にはコストがかかります。
  • プロジェクト管理ファイルを再生成したら、Xcode プロジェクトを開き直す必要があります。※1
  • CocoaPod を使った PJ の場合、XcodeGenからプロジェクトファイルを生成後に、毎回 pod install しないといけない ※2

※1 プロジェクト管理ファイル生成後に、そのまま Run 実行すると以下のエラーが表示されます。 開発時はどんどんファイルを追加していくので、都度、プロジェクト管理ファイルを再生成するのではなく、区切りがよくなったタイミングで、生成する運用をすれば、プロジェクトを開き直す回数も減らせるので大きな問題にはならないでしょう。

Build operations are disabled: ‘project.xcworkspace’ has changed and is reloading.

※2 pod installを行うと、project.pbxprojに Pod の情報が書き込まれますが、XcodeGen によるプロジェクト管理ファイル生成後、Pod 情報が消えるため Pods が正しく開けなくなります。そのため、毎回 pod installする必要があります。

pod install が必要なことは、オフィシャルに書かれています。

Use your Podfile as normal. The pods themselves don’t need to be referenced in the project spec. After you generate your project simply run pod install which will integrate with your project and create a workspace.

XcodeGen を使った Xcode プロジェクト作成

XcodeGen を使ったプロジェクトを作ります。

成果物はこちらです。 SwiftBoilerplate

プロジェクトの構成要素

  • Mint
  • XcodeGen
  • SwiftFormat
  • SwiftLint
  • SwiftGen
  • Carthage

Mint

Swift 製のパッケージ管理ツールです。 Homebrew みたいなものですが、各 PJ 毎にパッケージのバージョンを指定することが出来ます。 もっと知りたい方はMint で Swift 製のコマンドラインツールを管理するを御覧ください。

今回のプロジェクトでは、Mintfile というファイルを用意して、その中に、インストールしたいパッケージを列挙しているため mint bootstrap により、複数のパッケージをまとめてインストールしてくれるのでとても楽です。

  • Mintfile
yonaskolb/xcodegen
nicklockwood/SwiftFormat
realm/SwiftLint
SwiftGen/SwiftGen

実際のプロダクト時は、パッケージに @xxx.xxx.xxxをつけてバージョン管理するかと思います。

コマンドを追加(管理)するのに installbootstrap がありますが挙動が異なります。

install の場合は、 /usr/local/bin 以下に対象のパッケージがインストールさせるため、PATH 解決することで、直接 swiftlint のようにパスを書かずにコマンドが実行できますが、 bootstrapの場合は/usr/local/binにはパッケージがインストールされないため(これによりプロジェクト毎にバージョンを指定することができる) mint run swiftlint swiftlint と指定する必要があります。swiftlintが 2 つ並んでいる最初は、パッケージ名です。

そのため、XcodeRunScript 作成時にどちらでインストールしたかで記述が異なります。

  • install
if which swiftlint >/dev/null; then
  swiftlint
else
  echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi
  • bootstrap
if which swiftlint >/dev/null; then
  mint run swiftlint swiftlint
else
  echo "warning: Mint not installed, download from https://github.com/yonaskolb/Mint"
fi

よく使うコマンドですが、インストールされているパッケージを確認

mint list
🌱  Installed mint packages:
  SwiftFormat
    - 0.44.2
  SwiftGen
    - 6.1.0
  SwiftLint
    - 0.38.2
  XcodeGen
    - 2.13.0

SwiftFormat

コードのフォーマットを自動的に整形してくれるものです。.swiftformatをプロジェクト直下に用意することでどのルールを適用外にするかなどの調整が可能となります。(また、Xcode バージョンで書かれているかの判別に、.swift-version が必要)

SwiftLint

Swift のスタイルを強制するためのツールです。あまりルールが厳しいと、守れなくなるので、.swiftlint.yml で調整します。

Swift の静的解析ツール「SwiftLint」のセットアップ方法

SwiftGen

R.swift の方が有名ですが、注目されていましたので、試しに導入しました。 画像、文字などのリソースを自動的に生成して、型付を行ってくれるライブラリです。 タイポしなかったり、Xcode 補完が効くようになるので便利です。 R.swift または SwiftGen は生産性を大きく向上させるのでデフォルトで入れておきたい。

Carthage

XcodeGen で Carthage をでライブラリをインストールするときは、

carthage update

でライブラリをインストールしてから、

projext.yml に

targets:
  SwiftBoilerplate:
    dependencies:
      - carthage: Kingfisher
      - carthage: KingfisherSwiftUI

を追加すれば OK です。

Carthageに書いてありますが、 Run Script の追加や、RunScript に “Input Files”、“Output Files”を追加したパッケージを書く作業は不要です。

XcodeGen が自動的に追加してくれます。