web-dev-qa-db-ja.com

アプリケーションの設定バンドルでアプリケーションのバージョンリビジョンを表示するにはどうすればよいですか?

アプリケーションの設定バンドルに、アプリケーションバージョンと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ファイルを処理(前処理)し、ソースファイルに影響を与えずにリビジョン番号を置き換える方法です。

82

私は、pListcompiler( http://sourceforge.net/projects/plistcompiler )オープンソースプロジェクトを使用して、私がやりたいことを何とかしました。

  1. このコンパイラを使用すると、次の形式を使用して.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
                    ]
                }
            ]
        }
    }
    
  2. Brad-larson here で説明されているように、リポジトリリビジョンを.hファイルに抽出するカスタム実行スクリプトビルドフェーズがありました。

  3. Plcファイルには、#define、#message、#if、#Elif、#include、#warning、#ifdef、#else、#pragma、#error、#ifndef、#endif、xcode環境変数などのプリプロセッサディレクティブを含めることができます。そのため、次のディレクティブを追加することで変数kRevisionNumberを参照できました

    #include "Revision.h"
    
  4. また、xcodeターゲットにカスタムスクリプトビルドフェーズを追加して、プロジェクトがビルドされるたびにplcompilerを実行します

    /usr/local/plistcompiler0.6/plcompile -dest Settings.bundle -o Root.plist Settings.plc
    

そしてそれはそれでした!

3

前の回答のいずれよりもはるかに簡単な別のソリューションがあります。 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は対話モードになり、変更を保存する前に複数のコマンドを発行できます。ビルドスクリプトに組み込む前にこれを行うことをお勧めします。

68
Quinn Taylor

私の怠け者の解決策は、アプリケーションコードからバージョン番号を更新することでした。 Root.plistにデフォルト(または空白)の値を設定してから、スタートアップコードのどこかに:

NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
[[NSUserDefaults standardUserDefaults] setObject:version forKey:@"version_preference"];

唯一の問題は、更新されたバージョンを設定パネルに表示するために、アプリを少なくとも1回実行する必要があることです。

アイデアをさらに進めて、たとえば、アプリが起動された回数のカウンター、またはその他の興味深い情報を更新できます。

64

@Quinnの答えに基づいて、ここで私がこれを行うために使用する完全なプロセスと作業コードを示します。

  • アプリに設定バンドルを追加します。名前を変更しないでください。
  • テキストエディターで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>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にあります。

59
Ben Clayton

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に書き込むことには、いくつかの利点があります。

  1. リポジトリの作業コピー内のファイルを変更しません。
  2. Settings.bundle$SRCROOTへのパスを大文字にする必要はありません。パスは異なる場合があります。

Xcode 7.3.1でのテスト

20
hiroshi

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>
12
mrwalker

他の回答は、1つの理由で正しく機能しません。設定バンドルがパッケージ化されるまで、スクリプトのビルドフェーズは実行されません。したがって、Info.plistのバージョンが2.0.11で、それを2.0.12に更新し、プロジェクトをビルド/アーカイブしても、設定バンドルには2.0.11と表示されます。設定バンドルRoot.plistを開くと、ビルドプロセスの終了までバージョン番号が更新されないことがわかります。プロジェクトをもう一度ビルドして設定バンドルを正しく更新するか、代わりにスクリプトをビルド前フェーズに追加できます...

  • XCodeで、プロジェクトターゲットのスキームを編集します
  • BUILDスキームの開示矢印をクリックします
  • 次に、「事前アクション」項目をクリックします
  • プラス記号をクリックして、「新規スクリプト実行アクション」を選択します
  • シェル値を/ bin/shに設定します
  • 「ビルド設定の提供元」をプロジェクトターゲットに設定します
  • スクリプトをテキスト領域に追加します。次のスクリプトがうまくいきました。プロジェクトのセットアップに合わせてパスを変更する必要がある場合があります。

    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を開いてプロジェクトをビルド/アーカイブすると、ビルドプロセスの開始時にバージョン番号が更新され、設定バンドルに正しいバージョンが表示されるようになります。

8
Andy

this answerthis 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

これにより、プロジェクト内でこれらの値が変更されたときに変数を置換するトリックを行う必要があります。

1
Brad Larson

@Ben Claytonの回答と@Luis Ascorbeと@Vahid Amiriのコメントに基づく私の実例:

注:このアプローチは、リポジトリの作業コピーのSettings.bundle/Root.plistファイルを変更します

  1. プロジェクトのルートに設定バンドルを追加します。名前を変更しないでください
  2. 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>
    
  3. プロジェクト(ターゲット)スキームのビルド、プリアクションセクションに次のスクリプトを追加します

    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"
    
  4. 現在のスキームをビルドして実行する

1
Peter Kreinz

上記の回答は私にとってはうまくいかなかったため、カスタムスクリプトを作成しました。

これにより、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>

Working sample Root.plist entry

0
dheeraj_jha