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.
J'ai réussi à faire ce que je voulais en utilisant le projet open source pListcompiler ( http://sourceforge.net/projects/plistcompiler ).
À 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
]
}
]
}
}
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 .
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"
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!
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.
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.
Basé sur la réponse de @ Quinn, voici le processus complet et le code de travail que j'utilise pour le faire.
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.
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.
Settings.bundle
dans $SRCROOT
. Le chemin peut varier. Test sur Xcode 7.3.1
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>
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 ...
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.
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.
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.
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>
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"
Construire et exécuter le schéma actuel
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>