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

StackOverflow https://stackoverflow.com/questions/877128

Вопрос

Я хотел бы включить версию приложения и внутреннюю редакцию, что-то вроде 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 во время сборки и заменить номер редакции, не затрагивая исходный файл.

Это было полезно?

Решение 7

Мне удалось сделать то, что я хотел, используя 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. У меня была фаза сборки пользовательского сценария запуска, которая извлекала версию моего репозитория в файл .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
    

И это было все!

Другие советы

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

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

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

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

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

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

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

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

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

Основываясь на ответе @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 на ваше фактическое название приложения, а 1 после PreferenceSpecifiers будет индексом вашей записи версии в настройках.Приведенный выше пример Root.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)

Вот 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>

Другие ответы не работают корректно по одной причине:Этап сборки run script выполняется только после того, как Пакет настроек будет упакован.Итак, если ваша версия Info.plist 2.0.11 и вы обновите ее до 2.0.12, а затем соберете / заархивируете свой проект, в пакете настроек все равно будет указано 2.0.11.Если вы откроете пакет настроек Root.plist, вы увидите, что номер версии не обновляется до ОКОНЧАНИЯ процесса сборки.Вы можете создать проект ЗАНОВО, чтобы корректно обновить пакет настроек, или вместо этого добавить сценарий на этап предварительной сборки...

  • В XCode Отредактируйте Схему для вашего целевого проекта
  • Щелкните стрелку раскрытия на схеме ПОСТРОЕНИЯ
  • Затем нажмите на пункт "Предварительные действия"
  • Нажмите на знак плюс и выберите "Новое действие запуска скрипта".
  • Установите значение оболочки в /bin/sh
  • Установите "Предоставить параметры сборки из" в качестве цели вашего проекта
  • Добавьте свой скрипт в текстовую область.Следующий сценарий сработал для меня.Возможно, вам потребуется изменить пути в соответствии с настройками вашего проекта:

    versionString=$(/usr/libexec/PlistBuddy -c "Распечатать CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}")

    /usr/libexec/PlistBuddy "$SRCROOT/Settings.bundle/Root.plist" -c "установить параметры предпочтения: 0:значение по умолчанию $versionString"

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

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

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

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

Это должно привести к замене переменной при изменении этих значений в вашем проекте.

Мой рабочий пример, основанный на ответе @Ben Clayton и комментариях @Luis Ascorbe и @Vahid Amiri:

Примечание:Этот подход изменяет Настройки.пакет/Root.plist файл в рабочей копии репозитория

  1. Добавьте пакет настроек в корневой каталог вашего проекта.Не переименовывайте его
  2. Откройте 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. Добавьте следующий сценарий в раздел "Сборка, предварительные действия" схемы проекта (target)

    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. Создайте и запустите текущую схему

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top