Help us understand the problem. What is going on with this article?

【XcodeGen】で、AdHoc配信までできるiOSプロジェクトを作った話

More than 1 year has passed since last update.

tldr

  • xcodegenでちゃんとAdHoc配信までできる設定をするのは結構大変

-> なので、自分で頑張って作ってみました。あとXcodeGenの考察を色々します。

はじめに

どうも。新卒1年目のiOSエンジニアです。

  • XcodeGenでプロジェクト管理をする
  • 完成したアプリはdeploygateで配信する

という要件のiOSプロジェクトに先日まで参加していたのですが、色々苦労したので、そのときの話を語ります。

そもそもXcodeGenって

iOSプロジェクトを複数人で開発する場合、プロジェクトのファイルを管理する.xcodeprojファイルのコンフリクトがよく起こります。大規模開発だとよく起こるトラブル(らしい)です。

これを解消するのがXcodeGenで、プロジェクトのソースやビルド設定などをyamlファイルで定義し、yamlファイルとソースコードから開発環境となる.xcodeprojファイルを一意に生成できるツールです。即ち、.xcodeprojがgit上に無くても、yamlファイルさえあれば開発環境を他の開発者のPCで再現できるようになります。

.xcodeprojファイルを共有せずに済む仕組みとツールがあれば、そもそもコンフリクトとか起こらないよね! :smile: という寸法です。

Xcodegenを使う

XcodeGenでgenerateするまで

READMEを見れば大体わかりますが、インストールして、

$ brew install xcodegen

依存しているライブラリとソースコードを入れるディレクトリの準備をして
(ソースコードを入れるディレクトリは先に用意しないとxcodegen generateできません)

$ cd (プロジェクトルート)
$ mkdir (ソースコードを入れるディレクトリ)

$ pod init
$ vi Podfile
$ pod install

$ vi Cartfile
$ carthage bootstrap --no-use-binaries --cache-builds --platform ios

yamlファイルを書いて (後述)

$ vi project.yaml

generateします。歯車3つ出てきたら成功です :tada:

$ xcodegen generate
Loaded project:
  Name: testProject
  Targets:
    testProject: iOS application
⚙️  Generating plists...
⚙️  Generating project...
⚙️  Writing project...
Created project at ($PROJECT_ROOT)/.xcodeproj

$ ls
$PROJECT_NAME         Package.swift         Pods                  Sources               project.yml
Cartfile              Podfile               README.md             Tests                 testProject.xcodeproj

生成されたら容赦無くプロジェクトを開いてやりましょう。CocoaPodsを使う場合は.xcworkspaceも一緒に生成されているので無問題です :thumbsup:

$ open testProject.xcworkspace

project.yamlを書く

配信しない(とりあえずprojectファイルを生成して開発したい)場合

これ↓だけあればとりあえずprojectファイルが作れます。

project.yaml
name: testProject
  deploymentTarget:
    iOS: "11.0"
targets:
  testProject:
    platform: iOS 
    type: application
    sources:
      - path: testProject
      - path: testPeoject/R.generated.swift
        optional: true
    info:
      path: testProject/Info.plist
      properties:
        CFBundleDevelopmentRegion: ja_JP
        UISupportedInterfaceOrientations: [UIInterfaceOrientationLandscapeRight]
        UIRequiresFullScreen: "YES"
        UILaunchStoryboardName: "LaunchScreen"
        NSCameraUsageDescription: "カメラ撮影をするため" 
        CFBundleDisplayName: "AppName"
        CFBundleIdentifier: "com.skamada.testProject"
    dependencies:
      - carthage: RxSwift
      - carthage: RxCocoa
      - carthage: RxRelay
      - carthage: SwiftyBeaver
      - carthage: Reachability
      - carthage: Nuke
    preBuildScripts:
      - path: /bin/sh
        name: Run R.swift
        inputFiles:
          - $TEMP_DIR/rswift-lastrun
        outputFiles:
          - $SRCROOT/$PROJECT_NAME/R.generated.swift
        script: |
                "Pods/R.swift/rswift" generate "$SRCROOT/testProject/R.generated.swift"

ここで使っているのは

  • name プロジェクト名。
  • deploymentTarget 対応する(buildする)OSバージョン
    • sources ソースコードを格納するディレクトリ名。ディレクトリはあらかじめ作っておきましょう。
    • optional R.swiftのR.generated.swiftなど、ビルドして初めて生成されるファイルはoptional指定が必要です。
    • info Info.plistに設定したいことを羅列します。CF~~~とかUI~~~とか、Row Keysでの指定が必要です。XcodeのInfo.plistで右クリック > Show Row Keys/Valuesで1つずつ確認してみましょう。Info.plistの生成からしてくれます。
    • dependencies 依存するcarthageライブラリや、他のターゲット(target)、フレームワーク (framework)、sdk(sdk)を指定すれば、勝手に設定してくれます。
    • preBuildScripts R.swiftのように、ビルドの前後にスクリプトを走らせたい場合は設定しましょう。postBuildScriptsとか、postCompileScriptsとかもあります。

AdHoc配信をしたい(証明書、プロビ周りの設定をしたい)場合

こんなの↓を追加で設定してあげましょう。AdHoc配信のために必要なものはここでは説明しません。このあたりの記事を読んでみましょう。
【iOS】複雑な証明書周りをあっさり整理してみた

project.yaml
    settings:
      base:
        PRODUCT_BUNDLE_IDENTIFIER: "com.skamada.testProject"
        CODE_SIGN_STYLE: Manual
      configs:
        debug:
          CODE_SIGN_IDENTITY: iPhone Developer
          PROVISIONING_PROFILE_SPECIFIER: Project-profile-debug
          DEVELOPMENT_TEAM: # development teamのID
        release:
          CODE_SIGN_IDENTITY: iPhone Distribution
          PROVISIONING_PROFILE_SPECIFIER: Project-profile-release
          DEVELOPMENT_TEAM: # development teamのID
    scheme:
      targets:
        testProject
  • settings ここ↓の画面で設定できることをあれこれ設定できます。 スクリーンショット 2019-08-08 20.23.36.png
    • base: debugとかreleaseとかに共通して設定したいことを記述すると一気に設定してくれます。
    • PRODUCT_BUNDLE_IDENTIFIER 配信時の Bundle IDです。 CFBundleIdentifierと別個に設定しないといけないみたいです。
    • configs: debugとかreleaseとかで分けて設定したい場合は記入しましょう。
    • CODE_SIGN_IDENTITY iPhone Developerとか、iPhone Distributionとかです。
    • PROVISIONING_PROFILE_SPECIFIER プロビの名前を書きましょう。
    • DEVELOPMENT_TEAM Apple DeveloperのチームのIDを記入しましょう。チーム名ではありません。 (ここで数時間ハマりました)
    • scheme Build Scheme↓の設定です。この設定をしないと、Xcodeさんの気分次第でNo Schemeになってしまいます。
      スクリーンショット 2019-08-08 20.31.51.png

.gitignoreに追記する

.xcodeprojInfo.plistはproject.yamlから一意に生成できる
.xcodeprojInfo.plistはわざわざgit共有しなくてもいい

ので、gitignoreに追加してあげましょう。

.gitignore
Info.plist
*.xcworkspace
*.xcodeproj

project.yamlを作るのに苦労したところ

配信設定などは特に、project.yamlを作るのに結構苦労しました。

  • なぜ苦労したか
    • DEVELOPMENT_TEAMはチーム名でなくてチームIDに気づくのに時間がかかった
    • プロジェクトを完成させるのが最優先で、project.yamlを完成させるのは必須ではなかったから
    • 足りない設定は最悪プロジェクト生成後に手作業で生成すればいいから

DEVELOPMENT_TEAMはともかく、モチベーション的な要素が大きかった。
面倒ではあるけど、プロビの設定とかはXcode上でも2クリックくらいで済むので後回しになってました。何より先にちゃんと要件を満たしたコードを書かないと!と思うのが実装者の性。。。?

メリットとデメリットの整理

メリット

.xcprojectファイルがコンフリクトしない

そもそもgit共有しない運用ができるので。

targetの追加が楽

ビルドターゲットの追加はproject.yamlに数行追加するだけで済むので楽になるはずです。大規模になると恩恵が大きそう。

デメリット

ファイルツリーが強制的に同じ位置になる

「自分にとって見やすい配置」とかあると思うんです。でもXcodeGenだとアルファベット順強制です。
ちなみに、XcodeGenを使用するとこの仕様のおかげでファイルツリー構成が同じになるので、.xcodeprojをgitに共有しても.xcprojectコンフリクトはあんまり起こらない(はず)です。1

学習コストがかかる

ツールを導入するので当たり前ですが。設定を1つ追加するたびにREADMEを漁ることになるので学習コスト高めです。

git checkoutのたびにgenerateが必要

ライブラリ構成やファイルツリー構成がproject.yamlに依存するせいか、作業ブランチを変更するたびにgenerateしないとうまく動作しません。iOS開発に慣れている人ほど面倒くさいと感じるはず。

generatepod installはセットでやる

podとxcodeの仕様上仕方ないんだと思いますが、xcodegen generateをするたびにpod installしないと、podで導入したライブラリは認識されません。
即ち、作業ブランチを変える際は

git checkout ~~ -> xcodegen generate -> pod install

の3コマンドが必須になります。
3コマンドとなると結構手間なので、コマンドのaliasを作成するなどして対応するのが吉です。

さいごに:無理して全部のプロジェクトに導入しなくていい。でも1回試してみよう

当然導入するとプロジェクトメンバー全員に対して大きめの学習コストが発生するし、XcodeGen導入によって受けられる恩恵はプロジェクト規模にかなり依存する印象でした(規模大きいほど恩恵大)。試しに使ってみてもいいですがどのプロジェクトに導入するかは考えた方が良さそうです。
とはいえ恩恵はしっかりあるので、せひ一度試してみてください。


  1. .gitignoreで.xcodeprojを共有しないようにするのは私オリジナルの運用方法です。コンフリクトのリスクを最小限に抑えたいならそもそも共有しなければいいじゃん、っていう発想になるよね :thinking: ってことでこの運用にしました。 

s-kamada
アプリつくるひと2年目(swift / java) ほんとうは言語仕様の深いところを掘る、みたいなニッチ&ギークだけど為になる記事を書けるようになりたい
https://github.com/s-kamada
caraquri
ネイティブモバイルアプリの開発を強みとする港区の開発会社。
https://caraquri.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした