Я хотел бы включить версию приложения и внутреннюю ревизию, например 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 во время сборки и замены номера версии, не затрагивая исходный файл.
источник
/usr/libexec/PlistBuddy -c "Set :PreferenceSpecifiers:0:DefaultValue ${newVersion}" "${TARGET_BUILD_DIR}/${CONTENTS_FOLDER_PATH}/Settings.bundle/Root.plist"
Решение моего ленивого человека состояло в том, чтобы обновить номер версии из кода моего приложения. У вас может быть значение по умолчанию (или пустое) в Root.plist, а затем где-нибудь в вашем коде запуска:
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]; [[NSUserDefaults standardUserDefaults] setObject:version forKey:@"version_preference"];
Единственная загвоздка в том, что ваше приложение нужно будет запустить хотя бы один раз, чтобы обновленная версия появилась на панели настроек.
Вы можете развить идею дальше и обновить, например, счетчик того, сколько раз ваше приложение было запущено, или другую интересную информацию.
источник
CFBundleShortVersionString
иCFBundleVersion
то же значение,CFBundleShortVersionString
на самом деле Apple хочет, чтобы вы считали выпущенную версию именно тем , что вы показываете пользователям.CFBundleVersion
потенциально может быть внутренним номером версии, который вы, вероятно, не должны показывать пользователям (если он отличается).Основываясь на ответе @ 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>
Создайте этап сборки Run Script , переместите его после этапа Copy Bundle Resources . Добавьте этот код:
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 фактическим именем вашего приложения и цифрой 1 после PreferenceSpecifiers, которая будет индексом вашей записи Version в Настройках. В приведенном выше примере Root.plist он имеет индекс 1.
источник
buildVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${PROJECT_DIR}/${INFOPLIST_FILE}")
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:3:DefaultValue $buildVersion" "${SRCROOT}/Settings.bundle/Root.plist"
${INFOPLIST_PATH}
для информационного пути plistИспользование 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
in$SRCROOT
. Путь может отличаться.Тестирование на Xcode 7.3.1
источник
На примере здесь , вот сценарий, который я использую для автоматического обновления номера версии пакета настроек:
#! /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)
Вот Root.plist, который у меня есть в Settings.bundle:
<?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>
источник
NSDictionary
(и не осознавал, что это дает вам такой легкий доступ к файлам plist)gitHash = subprocess.check_output(["git", "rev-parse", "--short", "HEAD"]).rstrip()
Другие ответы не работают правильно по одной причине: этап сборки сценария запуска не выполняется до тех пор, пока ПОСЛЕ пакета настроек не будет упакован. Итак, если ваша версия Info.plist - 2.0.11, и вы обновите ее до 2.0.12, а затем соберите / заархивируйте свой проект, в пакете настроек все равно будет указано 2.0.11. Если вы откроете пакет настроек Root.plist, вы увидите, что номер версии не обновляется до КОНЕЦ процесса сборки. Вы можете построить проект СНОВА, чтобы правильно обновить пакет настроек, или вместо этого можете добавить сценарий на этап предварительной сборки ...
Добавьте свой скрипт в текстовую область. У меня сработал следующий сценарий. Возможно, вам потребуется изменить пути в соответствии с настройками вашего проекта:
versionString = $ (/ usr / libexec / PlistBuddy -c "Печать CFBundleVersion" "$ {PROJECT_DIR} / $ {INFOPLIST_FILE}")
/ usr / libexec / PlistBuddy "$ SRCROOT / Settings.bundle / Root.plist" -c "set PreferenceSpecifiers: 0: DefaultValue $ versionString"
Это правильно запустит скрипт ДО того, как пакет настроек будет упакован во время процесса сборки / архивирования. Если вы откроете пакет настроек Root.plist и соберете / заархивируете свой проект, вы увидите, что номер версии обновлен в начале процесса сборки, и ваш пакет настроек отобразит правильную версию.
источник
С Xcode 11.4 вы можете использовать следующие шаги, чтобы отобразить версию приложения в пакете настроек вашего приложения.
Набор
$(MARKETING_VERSION)
и$(CURRENT_PROJECT_VERSION)
переменныеПримечание: если
$(MARKETING_VERSION)
и$(CURRENT_PROJECT_VERSION)
переменные появляются дляBundle version string (short)
иBundle version
ключей в Info.plist , вы можете пропустить следующие шаги и перейти к следующему разделу.0.1.0
) и измените содержимое поля « Сборка» на какое-либо новое значение (например12
). Эти 2 изменения будут создавать$(MARKETING_VERSION)
и$(CURRENT_PROJECT_VERSION)
переменные в Info.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="$MARKETING_VERSION" build="$CURRENT_PROJECT_VERSION" /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:DefaultValue $version ($build)" "${SRCROOT}/Settings.bundle/Root.plist"
Запустить приложение
Источники
источник
Set: Entry, "PreferenceSpecifiers:0:DefaultValue", Does Not Exist
/usr/libexec/PlistBuddy "$SRCROOT/AppName/Settings.bundle/Root.plist" -c "set PreferenceSpecifiers:0:DefaultValue $version"
($build)
Мне удалось сделать то, что я хотел, используя проект с открытым исходным кодом 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 ] } ] } }
У меня была фаза сборки настраиваемого сценария запуска, которая извлекала мою версию репозитория в файл .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
Вот и все!
источник
Мой рабочий пример, основанный на ответе @Ben Clayton и комментариях @Luis Ascorbe и @Vahid Amiri:
Добавьте пакет настроек в корень вашего проекта. Не переименовывать это
Откройте Settings.bundle / Root.plist как SourceCode
Замените содержимое на:
<?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" - версия, которая будет отображаться в заголовке.
И имя идентификатора "var version" ниже для заголовка в settings.bundle Root.plist
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>
источник
Я считаю, что вы можете сделать это, используя способ, аналогичный тому, что я описываю в этом ответе (на основе этого сообщения ).
Во-первых, вы можете сделать VersionValue переменной в Xcode, переименовав ее в $ {VERSIONVALUE}. Создайте файл с именем versionvalue.xcconfig и добавьте его в свой проект. Перейдите к цели вашего приложения и перейдите к настройкам сборки для этой цели. Я считаю, что вам нужно добавить VERSIONVALUE в качестве пользовательского параметра сборки. В правом нижнем углу этого окна измените значение «На основе» на «значение версии».
Наконец, перейдите к своей цели и создайте этап сборки Run Script. Проверьте этап «Выполнить сценарий» и вставьте свой сценарий в текстовое поле «Сценарий». Например, мой сценарий для пометки моего параметра BUILD_NUMBER текущей сборкой Subversion выглядит следующим образом:
REV=`/usr/bin/svnversion -nc ${PROJECT_DIR} | /usr/bin/sed -e 's/^[^:]*://;s/[A-Za-z]//'` echo "BUILD_NUMBER = $REV" > ${PROJECT_DIR}/buildnumber.xcconfig
Это должно помочь заменить переменную при изменении этих значений в вашем проекте.
источник
Для меня это было самым простым решением:
Добавьте новую фазу сборки скрипта перед шагом Копировать ресурсы пакета
Оболочка:
/usr/bin/env python
Содержание:
#! /usr/bin/env python import os from AppKit import NSMutableDictionary # Key to replace settings_key = 'version_preference' # the key of your settings version # File path settings_path = os.environ.get('SRCROOT') + "/TheBeautifulNameOfYourOwnApp/Settings.bundle/Root.plist" # Composing version string version_string = os.environ.get('MARKETING_VERSION') + " (" + os.environ.get('CURRENT_PROJECT_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'] = version_string # Save new settings settings_plist.writeToFile_atomically_(settings_path, True)
источник