ちょっと前から…、いやだいぶ前になっちゃうのかな…。いまは iOS アプリを申請する時に Version
と Build
の値を意識して使い分けるようにしないといけなくなっていると思います。
超ざっくり言うと Version
が AppStore 上でも表示されるバージョン番号で、申請する時はこのバージョン番号でビルドしたアーカイブをアップロードします。Build
は Version
に紐づくマイナーアップデート番号みたいな扱い(のよう)です。
iTunes Connect に申請する場合、Version
と Build
のセットが同じバイナリはアップロードできません。たとえば「Version=1.0.0, Build=1」でビルドしたバイナリをアップロードしたら、「Version=1.0.0, Build=1」のバイナリは二度とアップロードできません。もしなにか不具合などがあって審査前に更新したい場合は、通常は「Version=1.0.0, Build=2」みたいな感じで Build
番号をインクリメントすると思います。
でも、この採番作業って地味にめんどくさいですよね。というかこの値の書き換えをリポジトリにコミットするのかどうかとか悩ましいし。率直に言ってうっとしい。
というわけで、ビルド時に自動で Version
, Build
の値が反映されるようにしてみました。git で管理していることが前提です。
Version
に入る値は git tag で付けたタグの名前がそのまま入るので、 git tag 2.1.6 -m ""
みたいな感じで予めタグをつけておく必要があります。
Build
は、コミット回数が入ります。つまり生涯増え続ける値です。
あとついでに COMMIT_HASH
っていう名前で最終コミットのハッシュ値も格納しています。
実装方法
スクリプトの準備
以下のスクリプトをどっか適当なところに用意します。たとえば、プロジェクトのルートディレクトリに auto-versioning.py という名前でおきましょうか。
#! /usr/bin/python
# -*- coding: utf-8 -*-
import os
from subprocess import Popen, PIPE
from Foundation import NSMutableDictionary
version_number = os.popen4("git describe --abbrev=0")[1].read().strip()
build_number = os.popen4("git log --oneline | wc -l")[1].read().strip()
commit_hash = os.popen4("git log -1 --pretty=format:'%h'")[1].read().strip()
info_plist = os.environ['TARGET_BUILD_DIR'] + "/" + os.environ['EXECUTABLE_FOLDER_PATH'] + "/Info.plist"
plist = NSMutableDictionary.dictionaryWithContentsOfFile_(info_plist)
# プロダクションバージョン番号
plist['CFBundleShortVersionString'] = version_number
# ビルド番号
plist['CFBundleVersion'] = build_number
# git ハッシュ
plist['COMMIT_HASH'] = commit_hash
plist.writeToFile_atomically_(info_plist, 1)
Xcode の準備
Build Phases
の後ろの方に Run Script
を追加して、シェルコマンドとしてさっきのスクリプトを指定します。
python "${SRCROOT}/auto-versioning.py"
以上です。この状態でビルドすると、ビルドしたバイナリにバージョン番号とビルド番号が自動で入ってとてもいい感じです!
ちなみにすっごくわかりにくいのですが、コードから値を参照する場合は CFBundleShortVersionString
がバージョン番号で CFBundleVersion
がビルド番号です。なんでなんだろうね!
終わりに
これを書きながらふとググったりしていたら、ところさんが書いてる記事を見付けました。そういえば以前にも見た記憶が…。
Info.plist の直接書き換えは不安定 といったような記述がありますね。やり方更新したほうがいいのかなー。自分が紹介したやり方はもう何年もやっててこれといった不具合には出会ってないということは一応書いておきます(気付いてないだけなのかもしれないけど)。