web-dev-qa-db-fra.com

Comment puis-je afficher la révision de la version de l'application dans le groupe de paramètres de mon application?

J'aimerais inclure la version de l'application et la révision interne, quelque chose comme 1.0.1 (r1243), dans le groupe de paramètres de mon application.

Le fichier Root.plist contient un fragment comme celui-ci ...

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

et je voudrais remplacer la chaîne "VersionValue" au moment de la construction.

J'ai un script capable d'extraire le numéro de version de mon référentiel. Ce dont j'ai besoin, c'est d'un moyen de traiter (pré-traiter) le fichier Root.plist, au moment de la construction, et de remplacer le numéro de révision sans affecter le fichier source.

81

J'ai réussi à faire ce que je voulais en utilisant le projet open source pListcompiler ( http://sourceforge.net/projects/plistcompiler ).

  1. À l'aide de ce compilateur, vous pouvez écrire le fichier de propriétés dans un fichier .plc en utilisant le format suivant:

    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. J'avais une phase de construction de script d'exécution personnalisée qui consistait à extraire la révision de mon référentiel dans un fichier .h comme décrit par brad-larson ici .

  3. Le fichier plc peut contenir des directives de préprocesseur telles que #define, #message, #if, #Elif, #include, #warning, #ifdef, #else, #pragma, #error, #ifndef, #endif, variables d'environnement xcode. J'ai donc pu référencer la variable kRevisionNumber en ajoutant la directive suivante

    #include "Revision.h"
    
  4. J'ai également ajouté une phase de construction de script personnalisé à ma cible xcode pour exécuter le compilateur de compilation à chaque fois que le projet est construit.

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

Et c'était ça!

3

Il existe une autre solution qui peut être beaucoup plus simple que l’une des réponses précédentes. Apple regroupe un outil de ligne de commande appelé PlistBuddy dans la plupart de ses programmes d'installation et l'a inclus dans Leopard à l'adresse /usr/libexec/PlistBuddy.

Puisque vous voulez remplacer VersionValue, en supposant que la valeur de la version soit extraite dans $newVersion, vous pouvez utiliser cette commande:

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

Nul besoin de jouer avec des expressions sed ou régulières, cette approche est relativement simple. Voir la page de manuel pour des instructions détaillées. Vous pouvez utiliser PlistBuddy pour ajouter, supprimer ou modifier une entrée dans une liste de propriétés. Par exemple, un de mes amis a blogué sur incrémenter les numéros de build dans Xcode en utilisant PlistBuddy.

Remarque: Si vous ne fournissez que le chemin d'accès au plist, PlistBuddy entre en mode interactif afin que vous puissiez émettre plusieurs commandes avant de décider d'enregistrer les modifications. Je recommande vivement de le faire avant de le placer dans votre script de construction.

68
Quinn Taylor

La solution de mon homme paresseux était de mettre à jour le numéro de version à partir du code de mon application. Vous pouvez avoir une valeur par défaut (ou vide) dans le fichier Root.plist, puis quelque part dans votre code de démarrage:

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

Le seul problème est que votre application devrait être exécutée au moins une fois pour que la version mise à jour apparaisse dans le panneau des paramètres.

Vous pouvez aller plus loin dans l'idée et mettre à jour, par exemple, un compteur du nombre de lancements de votre application ou d'autres informations intéressantes.

64
Vikram Kriplaney

Basé sur la réponse de @ Quinn, voici le processus complet et le code de travail que j'utilise pour le faire.

  • Ajoutez un ensemble de paramètres à votre application. Ne le renomme pas.
  • Ouvrez Settings.bundle/Root.plist dans un éditeur de texte

Remplacez le contenu par:

<?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>
  • Créez une phase Exécuter le script génération, à déplacer après la phase Copier les ressources du bundle . Ajoutez ce code:

    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"
    
  • Remplacez MyAppName par le nom actuel de votre application et le 1 après PreferenceSpecifiers pour qu'il soit l'index de votre entrée Version dans les paramètres. L'exemple ci-dessus de Root.plist l'a à l'index 1.

59
Ben Clayton

Utilisation de la partition de Ben Clayton https://stackoverflow.com/a/12842530/338986

Ajoutez Run script avec l'extrait suivant après 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"

Ajout de CFBundleVersion en plus de CFBundleShortVersionString. Il émet une version comme celle-ci:

En écrivant à $CODESIGNING_FOLDER_PATH/Settings.bundle/Root.plist Au lieu de celui dans $SRCROOT, vous bénéficiez d'avantages.

  1. Cela ne modifie pas les fichiers dans la copie de travail du référentiel. 
  2. Vous n'avez pas besoin de caser le chemin d'accès à Settings.bundle dans $SRCROOT. Le chemin peut varier. 

Test sur Xcode 7.3.1

15
hiroshi

Sur la base de l'exemple ici , voici le script que j'utilise pour mettre à jour automatiquement le numéro de version de l'ensemble de paramètres:

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

Voici le Root.plist que j'ai dans 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>
12
mrwalker

Les autres réponses ne fonctionnent pas correctement pour une raison: La phase de construction du script d’exécution n’est exécutée que si APRÈS l’ensemble des paramètres a été empaqueté. Ainsi, si votre version d'Info.plist est 2.0.11 et que vous la mettez à jour en 2.0.12, puis générez/archivez votre projet, le paquetage Paramètres indiquera toujours 2.0.11. Si vous ouvrez le groupe de paramètres Root.plist, vous pouvez constater que le numéro de version ne sera pas mis à jour avant la fin du processus de génération. Vous pouvez créer le projet AGAIN pour que l'ensemble de paramètres soit mis à jour correctement ou ajouter le script à une phase de pré-construction à la place ...

  • Dans XCode, éditez le schéma pour votre cible de projet
  • Cliquez sur la flèche de divulgation sur le schéma BUILD
  • Ensuite, cliquez sur l'item "Pre-actions"
  • Cliquez sur le signe plus et choisissez "Nouvelle action de script d'exécution".
  • Définissez la valeur du shell sur/bin/sh
  • Définissez "Fournir les paramètres de construction de" à la cible de votre projet.
  • Ajoutez votre script à la zone de texte. Le script suivant a fonctionné pour moi. Vous devrez peut-être modifier les chemins en fonction de la configuration de votre projet:

    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"

Cela exécutera correctement le script AVANT que le paquet de paramètres ne soit emballé pendant le processus de construction/archivage. Si vous ouvrez le paquet de paramètres Root.plist et construisez/archivez votre projet, vous verrez maintenant que le numéro de version est mis à jour au début du processus de construction et que votre paquet de paramètres affichera la version correcte.

7
Andy

Je pense que vous pouvez le faire en utilisant une méthode similaire à celle décrite dans cette réponse (basé sur cet article ). 

Premièrement, vous pouvez faire de VersionValue une variable dans Xcode en le renommant $ {VERSIONVALUE}. Créez un fichier nommé versionvalue.xcconfig et ajoutez-le à votre projet. Accédez à la cible de votre application et accédez aux paramètres de construction de cette cible. Je pense que vous devez ajouter VERSIONVALUE en tant que paramètre de construction défini par l'utilisateur. Dans le coin inférieur droit de cette fenêtre, définissez la valeur Based On sur "versionvalue".

Enfin, accédez à votre cible et créez une phase de génération de script d’exécution. Inspectez cette phase d’exécution du script et collez-le dans le champ de texte Script. Par exemple, mon script pour baliser mon paramètre BUILD_NUMBER avec la version actuelle de Subversion est le suivant: 

REV=`/usr/bin/svnversion -nc ${PROJECT_DIR} | /usr/bin/sed -e 's/^[^:]*://;s/[A-Za-z]//'`
echo "BUILD_NUMBER = $REV" > ${PROJECT_DIR}/buildnumber.xcconfig

Cela devrait permettre de remplacer la variable lorsque ces valeurs changent dans votre projet.

1
Brad Larson

Mon exemple de travail basé sur la réponse de @Ben Clayton et les commentaires de @Luis Ascorbe et de @Vahid Amiri:

Remarque: cette approche modifie le fichier Settings.bundle/Root.plist dans la copie de travail du référentiel. 

  1. Ajoutez un ensemble de paramètres à la racine de votre projet. Ne le renomme pas
  2. Ouvrez Settings.bundle/Root.plist en tant que SourceCode 

    Remplacez le contenu par:

    <?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. Ajoutez le script suivant à la section Build, Pre-actions du schéma de projet (cible)

    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. Construire et exécuter le schéma actuel

0
Peter Kreinz

Les réponses ci-dessus n'ont pas fonctionné pour moi, c'est pourquoi j'ai créé mon script personnalisé.

Ceci met à jour dynamiquement l'entrée de Root.plist

Utilisez le script ci-dessous. W travaillera à coup sûr vérifié dans xcode 10.3.

"var buildVersion" est la version à afficher dans le titre.

Et le nom de l'identifiant est "version var" ci-dessous pour le titre dans 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

Exemple d'entrée dans 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