Как я могу отобразить версию версии приложения в пакете настроек моего приложения?


Я хотел бы включить версию приложения и внутреннюю ревизию, что-то вроде 1.0.1 (r1243), в комплект настроек моего приложения.

Корень.файл 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" во время сборки.

У меня есть скрипт, который может извлечь номер версии из моего репозитория, что мне нужно, это способ обработки (предварительной обработки) корня.файл plist, во время сборки, и замените номер редакции, не затрагивая исходный файл.

8 80

8 ответов:

есть еще одно решение, которое может быть гораздо проще, чем любой из предыдущих ответов. Apple связывает инструмент командной строки под названием PlistBuddy внутри большинства его установщиков, и включил его в Leopard at /usr/libexec/PlistBuddy.

так как вы хотите заменить VersionValue, предполагая, что у вас есть значение версии, извлеченное в $newVersion, вы можете использовать эту команду:

/usr/libexec/PlistBuddy -c "Set :VersionValue $newVersion" /path/to/Root.plist

не нужно возиться с sed или регулярными выражениями, этот подход довольно простой. Смотрите на странице для получения подробных инструкций. PlistBuddy можно использовать для добавления, удаления или изменения любой записи в списке свойств. Например, мой друг написал в блоге о увеличение числа сборок в Xcode С помощью PlistBuddy.

Примечание: если вы указываете только путь к plist, PlistBuddy переходит в интерактивный режим, поэтому вы можете выполнить несколько команд, прежде чем принимать решение о сохранении изменений. Я определенно рекомендую сделать это перед тем, как плюхнуть его в свой скрипт сборки.

решение моего ленивого человека состояло в том, чтобы обновить номер версии из моего кода приложения. У вас может быть значение по умолчанию (или пустое) в корне.plist и затем, где-то в вашем коде запуска:

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

единственная загвоздка в том, что ваше приложение должно быть запущено хотя бы один раз, чтобы обновленная версия появилась на панели настроек.

вы можете взять идею дальше и обновить, например, счетчик того, сколько раз ваше приложение было запущено, или другие интересные бит информации.

основываясь на ответе @Quinn, здесь полный процесс и рабочий код, который я использую для этого.

  • добавьте пакет настроек в свое приложение. Не переименовывайте его.
  • Открыть Настройки.связка / корень.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 на имя вашего фактического приложения, а 1 после PreferenceSpecifiers будет индексом вашей версии записи в настройках. Выше корень.пример plist имеет его в индексе 1.

используя 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

на примере здесь, вот скрипт, который я использую для автоматического обновления номера версии пакета настроек:

#! /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)

вот корень.плист у меня в настройках.бандл:

<?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>

другие ответы не работают по одной причине: Этап сборки сценария запуска не выполняется до тех пор, пока пакет параметров не будет упакован. Итак, если ваша информация.версия plist-2.0.11, и вы обновляете ее до 2.0.12, затем строите/архивируете свой проект, пакет настроек все равно будет говорить 2.0.11. Если вы откроете корневой пакет настроек.plist, вы можете видеть, что номер версии не обновляется до конца процесса сборки. Вы можете построить проект снова, чтобы получить настройки пакет обновлен правильно, или вы можете добавить сценарий на этапе предварительной сборки вместо этого...

  • в XCode отредактируйте схему для своей цели проекта
  • щелкните стрелку раскрытия на схеме сборки
  • затем нажмите на пункт "предварительные действия"
  • нажмите на знак плюс и выберите "новое действие сценария запуска"
  • установите значение оболочки в /bin / sh
  • установите "предоставить настройки сборки из" в целевой проект
  • добавить ваш скрипт в текстовую область. Следующий сценарий работал для меня. Возможно, Вам потребуется изменить пути в соответствии с настройкой проекта:

    versionString=$(/usr / libexec / PlistBuddy-c "Print CFBundleVersion "" ${PROJECT_DIR} / ${INFOPLIST_FILE}")

    /usr/libexec/PlistBuddy "$SRCROOT / Settings.связка / корень.plist "- c "set PreferenceSpecifiers:0: DefaultValue $versionString"

Это позволит правильно запустить скрипт до того, как пакет настроек будет упакован во время процесса сборки/архивирования. Если вы откроете корневой пакет настроек.plist и build / archive ваш проект, теперь вы увидите, что номер версии обновляется в начале процесса сборки, и ваш пакет настроек отобразит правильную версию.

мне удалось сделать то, что я хотел с помощью pListcompiler (http://sourceforge.net/projects/plistcompiler) open source porject.

  1. С помощью этого компилятора вы можете записать файл свойств в a .файл ПЛК в следующем формате:

    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. у меня был пользовательский этап сборки сценария запуска, который извлекал мою ревизию репозитория .H-файл, как описано Брэд-Ларсон здесь.

  3. файл ПЛК может содержать директивы препроцессора, такие как #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
    

и это все!

Я верю, что вы можете сделать это, используя способ, который похож на то, что я описываю в ответ (исходя из этот пост).

во-первых, вы можете сделать VersionValue переменной в Xcode, переименовав его в ${VERSIONVALUE}. Создайте файл с именем versionvalue.xcconfig и добавить его в свой проект. Перейдите к целевому приложению и перейдите к настройкам сборки для этого целевого объекта. Я считаю, что вам нужно добавить VERSIONVALUE в качестве пользовательского параметра сборки. В в правом нижнем углу этого окна измените значение на основе на "versionvalue".

наконец, перейдите к своей цели и создайте этап сборки сценария запуска. Проверьте этот этап выполнения сценария и вставьте его в текстовое поле сценария. Например, мой скрипт для пометки моего параметра 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

Это должно сделать трюк замены переменной, когда эти значения изменяются в вашем проекте.