アプリケーションの設定バンドルに、アプリケーションバージョンと1.0.1(r1243)などの内部リビジョンを含めたいと思います。
Root.plistファイルには、次のようなフラグメントが含まれています...
<dict>
<key>Type</key>
<string>PSTitleValueSpecifier</string>
<key>Title</key>
<string>Version</string>
<key>Key</key>
<string>version_preference</string>
<key>DefaultValue</key>
<string>VersionValue</string>
<key>Values</key>
<array>
<string>VersionValue</string>
</array>
<key>Titles</key>
<array>
<string>VersionValue</string>
</array>
</dict>
ビルド時に「VersionValue」文字列を置き換えたいと思います。
リポジトリからバージョン番号を抽出できるスクリプトがあります。必要なのは、ビルド時にRoot.plistファイルを処理(前処理)し、ソースファイルに影響を与えずにリビジョン番号を置き換える方法です。
私は、pListcompiler( http://sourceforge.net/projects/plistcompiler )オープンソースプロジェクトを使用して、私がやりたいことを何とかしました。
このコンパイラを使用すると、次の形式を使用して.plcファイルにプロパティファイルを書き込むことができます。
plist {
dictionary {
key "StringsTable" value string "Root"
key "PreferenceSpecifiers" value array [
dictionary {
key "Type" value string "PSGroupSpecifier"
key "Title" value string "AboutSection"
}
dictionary {
key "Type" value string "PSTitleValueSpecifier"
key "Title" value string "Version"
key "Key" value string "version"
key "DefaultValue" value string "VersionValue"
key "Values" value array [
string "VersionValue"
]
key "Titles" value array [
string "r" kRevisionNumber
]
}
]
}
}
Brad-larson here で説明されているように、リポジトリリビジョンを.hファイルに抽出するカスタム実行スクリプトビルドフェーズがありました。
Plcファイルには、#define、#message、#if、#Elif、#include、#warning、#ifdef、#else、#pragma、#error、#ifndef、#endif、xcode環境変数などのプリプロセッサディレクティブを含めることができます。そのため、次のディレクティブを追加することで変数kRevisionNumberを参照できました
#include "Revision.h"
また、xcodeターゲットにカスタムスクリプトビルドフェーズを追加して、プロジェクトがビルドされるたびにplcompilerを実行します
/usr/local/plistcompiler0.6/plcompile -dest Settings.bundle -o Root.plist Settings.plc
そしてそれはそれでした!
前の回答のいずれよりもはるかに簡単な別のソリューションがあります。 Appleは、ほとんどのインストーラー内にPlistBuddyと呼ばれるコマンドラインツールをバンドルしており、Leopardの/usr/libexec/PlistBuddy
に含まれています。 。
$newVersion
にバージョン値が抽出されていると仮定すると、VersionValue
を置き換えるため、次のコマンドを使用できます。
/usr/libexec/PlistBuddy -c "Set :VersionValue $newVersion" /path/to/Root.plist
Sedや正規表現をいじる必要はありません。このアプローチは非常に簡単です。詳細な手順については、 manページ をご覧ください。 PlistBuddyを使用して、プロパティリストのエントリを追加、削除、または変更できます。たとえば、私の友人が Xcodeでのビルド番号の増分 についてPlistBuddyを使用してブログを書いています。
注:plistへのパスのみを指定すると、PlistBuddyは対話モードになり、変更を保存する前に複数のコマンドを発行できます。ビルドスクリプトに組み込む前にこれを行うことをお勧めします。
私の怠け者の解決策は、アプリケーションコードからバージョン番号を更新することでした。 Root.plistにデフォルト(または空白)の値を設定してから、スタートアップコードのどこかに:
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
[[NSUserDefaults standardUserDefaults] setObject:version forKey:@"version_preference"];
唯一の問題は、更新されたバージョンを設定パネルに表示するために、アプリを少なくとも1回実行する必要があることです。
アイデアをさらに進めて、たとえば、アプリが起動された回数のカウンター、またはその他の興味深い情報を更新できます。
@Quinnの答えに基づいて、ここで私がこれを行うために使用する完全なプロセスと作業コードを示します。
内容を次のものに置き換えます。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.Apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Title</key>
<string>About</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>DefaultValue</key>
<string>DummyVersion</string>
<key>Key</key>
<string>version_preference</string>
<key>Title</key>
<string>Version</string>
<key>Type</key>
<string>PSTitleValueSpecifier</string>
</dict>
</array>
<key>StringsTable</key>
<string>Root</string>
</dict>
</plist>
スクリプトの実行ビルドフェーズを作成し、バンドルリソースのコピーフェーズの後に移動します。このコードを追加してください:
cd "${BUILT_PRODUCTS_DIR}"
buildVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${INFOPLIST_PATH}" )
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $buildVersion" "${WRAPPER_NAME}/Settings.bundle/Root.plist"
MyAppNameを実際のアプリの名前に置き換え、PreferenceSpecifiersの後の1を設定のバージョンエントリのインデックスに置き換えます。上記のRoot.plistの例では、インデックス1にあります。
Ben Claytonのplistの使用 https://stackoverflow.com/a/12842530/338986
Run script
の後に、次のスニペットでCopy Bundle Resources
を追加します。
version=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$PROJECT_DIR/$INFOPLIST_FILE")
build=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$PROJECT_DIR/$INFOPLIST_FILE")
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $version ($build)" "$CODESIGNING_FOLDER_PATH/Settings.bundle/Root.plist"
CFBundleVersion
に加えてCFBundleShortVersionString
を追加します。次のようなバージョンを出力します。
$CODESIGNING_FOLDER_PATH/Settings.bundle/Root.plist
の代わりに$SRCROOT
に書き込むことには、いくつかの利点があります。
Settings.bundle
の$SRCROOT
へのパスを大文字にする必要はありません。パスは異なる場合があります。Xcode 7.3.1でのテスト
例 here に基づいて、設定バンドルのバージョン番号を自動的に更新するために使用しているスクリプトを次に示します。
#! /usr/bin/env python
import os
from AppKit import NSMutableDictionary
settings_file_path = 'Settings.bundle/Root.plist' # the relative path from the project folder to your settings bundle
settings_key = 'version_preference' # the key of your settings version
# these are used for testing only
info_path = '/Users/mrwalker/developer/My_App/Info.plist'
settings_path = '/Users/mrwalker/developer/My_App/Settings.bundle/Root.plist'
# these environment variables are set in the XCode build phase
if 'PRODUCT_SETTINGS_PATH' in os.environ.keys():
info_path = os.environ.get('PRODUCT_SETTINGS_PATH')
if 'PROJECT_DIR' in os.environ.keys():
settings_path = os.path.join(os.environ.get('PROJECT_DIR'), settings_file_path)
# reading info.plist file
project_plist = NSMutableDictionary.dictionaryWithContentsOfFile_(info_path)
project_bundle_version = project_plist['CFBundleVersion']
# print 'project_bundle_version: '+project_bundle_version
# reading settings plist
settings_plist = NSMutableDictionary.dictionaryWithContentsOfFile_(settings_path)
for dictionary in settings_plist['PreferenceSpecifiers']:
if 'Key' in dictionary and dictionary['Key'] == settings_key:
dictionary['DefaultValue'] = project_bundle_version
# print repr(settings_plist)
settings_plist.writeToFile_atomically_(settings_path, True)
これが、Settings.bundleにあるRoot.plistです。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.Apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Title</key>
<string>About</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>DefaultValue</key>
<string>1.0.0.0</string>
<key>Key</key>
<string>version_preference</string>
<key>Title</key>
<string>Version</string>
<key>Type</key>
<string>PSTitleValueSpecifier</string>
</dict>
</array>
<key>StringsTable</key>
<string>Root</string>
</dict>
</plist>
他の回答は、1つの理由で正しく機能しません。設定バンドルがパッケージ化されるまで、スクリプトのビルドフェーズは実行されません。したがって、Info.plistのバージョンが2.0.11で、それを2.0.12に更新し、プロジェクトをビルド/アーカイブしても、設定バンドルには2.0.11と表示されます。設定バンドルRoot.plistを開くと、ビルドプロセスの終了までバージョン番号が更新されないことがわかります。プロジェクトをもう一度ビルドして設定バンドルを正しく更新するか、代わりにスクリプトをビルド前フェーズに追加できます...
スクリプトをテキスト領域に追加します。次のスクリプトがうまくいきました。プロジェクトのセットアップに合わせてパスを変更する必要がある場合があります。
versionString = $(/ usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$ {PROJECT_DIR}/$ {INFOPLIST_FILE}")
/ usr/libexec/PlistBuddy "$ SRCROOT/Settings.bundle/Root.plist" -c "set PreferenceSpecifiers:0:DefaultValue $ versionString"
これにより、設定/バンドルがビルド/アーカイブプロセス中にパッケージ化される前に、スクリプトが正しく実行されます。設定バンドルRoot.plistを開いてプロジェクトをビルド/アーカイブすると、ビルドプロセスの開始時にバージョン番号が更新され、設定バンドルに正しいバージョンが表示されるようになります。
this answer ( this post に基づいて)で説明した方法と同様の方法を使用してこれを行うことができると思います。
まず、$ {VERSIONVALUE}に名前を変更することにより、VersionValueをXcode内の変数にすることができます。 versionvalue.xcconfigという名前のファイルを作成し、プロジェクトに追加します。アプリケーションのターゲットに移動し、そのターゲットのビルド設定に移動します。 VERSIONVALUEをユーザー定義のビルド設定として追加する必要があると思います。そのウィンドウの右下隅で、「基準」値を「バージョン値」に変更します。
最後に、ターゲットに移動して、スクリプトの実行ビルドフェーズを作成します。 [スクリプトの実行]フェーズを調べて、[スクリプト]テキストフィールド内にスクリプトを貼り付けます。たとえば、現在のSubversionビルドでBUILD_NUMBER設定をタグ付けするスクリプトは次のとおりです。
REV=`/usr/bin/svnversion -nc ${PROJECT_DIR} | /usr/bin/sed -e 's/^[^:]*://;s/[A-Za-z]//'`
echo "BUILD_NUMBER = $REV" > ${PROJECT_DIR}/buildnumber.xcconfig
これにより、プロジェクト内でこれらの値が変更されたときに変数を置換するトリックを行う必要があります。
@Ben Claytonの回答と@Luis Ascorbeと@Vahid Amiriのコメントに基づく私の実例:
注:このアプローチは、リポジトリの作業コピーのSettings.bundle/Root.plistファイルを変更します
SourceCodeとしてSettings.bundle/Root.plistを開きます
内容を次のものに置き換えます。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.Apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>DefaultValue</key>
<string></string>
<key>Key</key>
<string>version_preference</string>
<key>Title</key>
<string>Version</string>
<key>Type</key>
<string>PSTitleValueSpecifier</string>
</dict>
</array>
<key>StringsTable</key>
<string>Root</string>
</dict>
</plist>
プロジェクト(ターゲット)スキームのビルド、プリアクションセクションに次のスクリプトを追加します
version=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$PROJECT_DIR/$INFOPLIST_FILE")
build=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$PROJECT_DIR/$INFOPLIST_FILE")
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:DefaultValue $version ($build)" "${SRCROOT}/Settings.bundle/Root.plist"
現在のスキームをビルドして実行する
上記の回答は私にとってはうまくいかなかったため、カスタムスクリプトを作成しました。
これにより、Root.plistからエントリが動的に更新されます
以下の実行スクリプトを使用します。 Xcode 10.3で検証済みであることは確かに機能します。
「var buildVersion」は、タイトルに表示されるバージョンです。
また、settings.bundle Root.plistのタイトルの識別子名は「var version」です。
cd "${BUILT_PRODUCTS_DIR}"
#set version name to your title identifier's string from settings.bundle
var version = "Version"
#this will be the text displayed in title
longVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${INFOPLIST_PATH}")
shortVersion=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" ${TARGET_BUILD_DIR}/${INFOPLIST_PATH})
buildVersion="$shortVersion.$longVersion"
path="${WRAPPER_NAME}/Settings.bundle/Root.plist"
settingsCnt=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:" ${path} | grep "Dict"|wc -l`
for (( idx=0; idx<$settingsCnt; idx++ ))
do
#echo "Welcome $idx times"
val=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:${idx}:Key" ${path}`
#echo $val
#if ( "$val" == "Version" )
if [ $val == "Version" ]
then
#echo "the index of the entry whose 'Key' is 'version' is $idx."
# now set it
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:${idx}:DefaultValue $buildVersion" $path
# just to be sure that it worked
ver=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:${idx}:DefaultValue" $path`
#echo 'PreferenceSpecifiers:$idx:DefaultValue set to: ' $ver
fi
done
Root.plistのエントリの例
<dict>
<key>Type</key>
<string>PSTitleValueSpecifier</string>
<key>Title</key>
<string>Version</string>
<key>DefaultValue</key>
<string>We Rock</string>
<key>Key</key>
<string>Version</string>
</dict>