wake-up-neo.com

Wie kann ich die Version der Anwendungsversion im Einstellungspaket der Anwendung anzeigen?

Ich möchte die Anwendungsversion und die interne Revision (z. B. 1.0.1 (r1243)) in das Einstellungspaket der Anwendung aufnehmen.

Die Root.plist-Datei enthält ein Fragment wie dieses ...

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

und ich möchte die Zeichenfolge "VersionValue" zur Buildzeit ersetzen.

Ich habe ein Skript, das die Versionsnummer aus meinem Repository extrahieren kann. Ich benötige eine Möglichkeit, die Datei Root.plist zur Buildzeit zu verarbeiten (vorzuverarbeiten) und die Revisionsnummer zu ersetzen, ohne die Quelldatei zu beeinflussen.

81

Ich habe es geschafft, was ich wollte, indem ich das Open Source-Projekt pListcompiler ( http://sourceforge.net/projects/plistcompiler ) verwendete.

  1. Mit diesem Compiler können Sie die Eigenschaftendatei in einer PLC-Datei mit folgendem Format schreiben:

    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. Ich hatte eine benutzerdefinierte Skriptphase, in der meine Repository-Revision in die .h-Datei extrahiert wurde, wie von brad-larson hier beschrieben.

  3. Die plc-Datei kann Präprozessoranweisungen enthalten, wie #define, #message, #if, #Elif, #include, #warning, #ifdef, #else, #pragma, #error, #ifndef, #endif, xcode-Umgebungsvariablen. So konnte ich auf die Variable kRevisionNumber durch Hinzufügen der folgenden Direktive verweisen

    #include "Revision.h"
    
  4. Ich fügte meinem Xcode-Ziel außerdem eine benutzerdefinierte Skript-Erstellungsphase hinzu, um den plcompiler jedes Mal auszuführen, wenn das Projekt erstellt wird

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

Und das war es!

3

Es gibt eine andere Lösung, die viel einfacher als jede der vorherigen Antworten sein kann. Apple bündelt ein Befehlszeilentool namens PlistBuddy in den meisten Installationsprogrammen und hat es in Leopard unter /usr/libexec/PlistBuddy integriert.

Da Sie VersionValue ersetzen möchten, vorausgesetzt, Sie haben den Versionswert in $newVersion extrahiert, können Sie diesen Befehl verwenden:

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

Es ist nicht notwendig, mit sed oder regulären Ausdrücken zu arbeiten. Dieser Ansatz ist recht einfach. Detaillierte Anweisungen finden Sie in der Manpage . Sie können PlistBuddy verwenden, um einen Eintrag in einer Eigenschaftsliste hinzuzufügen, zu entfernen oder zu ändern. Zum Beispiel hat ein Freund von mir mit PlistBuddy über Erhöhen der Build-Nummern in Xcode gebloggt.

Hinweis: Wenn Sie nur den Pfad zur plist angeben, wechselt PlistBuddy in den interaktiven Modus. Sie können also mehrere Befehle ausgeben, bevor Sie die Änderungen speichern. Ich empfehle es auf jeden Fall, bevor Sie es in Ihr Build-Skript schreiben.

68
Quinn Taylor

Die Lösung meines Lazy Man bestand darin, die Versionsnummer aus meinem Anwendungscode heraus zu aktualisieren. Sie könnten einen Standardwert (oder einen leeren Wert) in der Root.plist haben und dann irgendwo in Ihrem Startcode:

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

Der einzige Haken ist, dass Ihre App mindestens einmal ausgeführt werden muss, damit die aktualisierte Version im Einstellungsfenster angezeigt wird.

Sie können die Idee weiterführen und beispielsweise einen Zähler aktualisieren, wie oft Ihre App gestartet wurde, oder andere interessante Informationen.

64

Basierend auf der Antwort von @ Quinn verwende ich hier den vollständigen Prozess und Funktionscode, den ich dafür verwende.

  • Fügen Sie Ihrer App ein Einstellungspaket hinzu. Benennen Sie es nicht um.
  • Öffnen Sie Settings.bundle/Root.plist in einem Texteditor

Ersetzen Sie den Inhalt durch:

<?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>
  • Erstellen Sie eine Run ScriptBuild-Phase, bewegen Sie sich nach der Copy Bundle Resources -Phase. Fügen Sie diesen Code hinzu:

    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"
    
  • Ersetzen Sie MyAppName durch den Namen Ihrer tatsächlichen App und die 1 nach PreferenceSpecifiers als Index Ihres Versionseintrags in den Einstellungen. Das obige Beispiel für Root.plist hat den Index 1.

59
Ben Clayton

Ben Claytons Plist verwenden https://stackoverflow.com/a/12842530/338986

Fügen Sie Run script mit folgendem Code nach Copy Bundle Resources hinzu.

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"

Anhängen von CFBundleVersion zusätzlich zu CFBundleShortVersionString. Es gibt folgende Version aus:

Durch das Schreiben an $CODESIGNING_FOLDER_PATH/Settings.bundle/Root.plist Anstelle des Codes in $SRCROOT haben Sie einige Vorteile.

  1. Es dürfen keine Dateien in der Arbeitskopie des Repositorys geändert werden. 
  2. Der Pfad zu Settings.bundle in $SRCROOT muss nicht angegeben werden. Der Pfad kann variieren. 

Testen mit Xcode 7.3.1

15
hiroshi

Basierend auf dem Beispiel hier , wird hier das Skript verwendet, mit dem die Versionsnummer des Einstellungspakets automatisch aktualisiert wird:

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

Hier ist die Root.plist, die ich in Settings.bundle habe:

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

Die anderen Antworten funktionieren aus einem Grund nicht richtig: Die Build-Phase für das Ausführen des Skripts wird erst ausgeführt, nachdem das Einstellungspaket gepackt wurde. Wenn Ihre Info.plist-Version 2.0.11 ist und Sie sie auf 2.0.12 aktualisieren und Ihr Projekt dann erstellen/archivieren, wird das Einstellungspaket immer noch 2.0.11 anzeigen. Wenn Sie das Einstellungspaket Root.plist öffnen, können Sie feststellen, dass die Versionsnummer erst am Ende des Buildvorgangs aktualisiert wird. Sie können das Projekt WIEDER erstellen, um das Einstellungen-Bundle korrekt zu aktualisieren, oder Sie können das Skript stattdessen einer Vorbereitungsphase hinzufügen.

  • Bearbeiten Sie in XCode das Schema für Ihr Projektziel
  • Klicken Sie im BUILD-Schema auf den Offenlegungspfeil
  • Klicken Sie dann auf den Punkt "Voraktionen"
  • Klicken Sie auf das Pluszeichen und wählen Sie "Neue Skriptaktion ausführen".
  • Setzen Sie den Shell-Wert auf/bin/sh
  • Legen Sie "Projekteinstellungen festlegen von" für Ihr Projektziel fest
  • Fügen Sie Ihr Skript dem Textbereich hinzu. Das folgende Skript hat für mich funktioniert. Möglicherweise müssen Sie die Pfade ändern, um sie an Ihre Projektkonfiguration anzupassen:

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

    / usr/libexec/PlistBuddy "$ SRCROOT/Settings.bundle/Root.plist" -c "setze PreferenceSpecifiers: 0: DefaultValue $ versionString"

Dadurch wird das Skript korrekt ausgeführt, BEVOR das Einstellungspaket während des Erstellungs-/Archivierungsprozesses gepackt wird. Wenn Sie das Einstellungspaket Root.plist öffnen und Ihr Projekt erstellen/archivieren, wird die Versionsnummer zu Beginn des Erstellungsprozesses aktualisiert, und Ihr Einstellungspaket zeigt die richtige Version an.

7
Andy

Ich glaube, Sie können dies auf eine Weise tun, die der von this answer (basierend auf this post ) ähnlich ist. 

Erstens können Sie VersionValue zu einer Variablen in Xcode machen, indem Sie sie in $ {VERSIONVALUE} umbenennen. Erstellen Sie eine Datei mit dem Namen versionvalue.xcconfig und fügen Sie sie Ihrem Projekt hinzu. Gehen Sie zu Ihrem Anwendungsziel und zu den Build-Einstellungen für dieses Ziel. Ich glaube, dass Sie VERSIONVALUE als benutzerdefinierte Build-Einstellung hinzufügen müssen. Ändern Sie in der rechten unteren Ecke dieses Fensters den Wert für "Basierend auf" in "Versionswert".

Gehen Sie schließlich zu Ihrem Ziel und erstellen Sie eine Erstellungsphase für das Ausführen von Skripts. Überprüfen Sie die Skriptphase, und fügen Sie sie in das Skriptfeld ein. Mein Skript zum Markieren meiner BUILD_NUMBER-Einstellung mit dem aktuellen Subversion-Build lautet beispielsweise wie folgt: 

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

Dies sollte den Trick erfüllen, die Variable zu ersetzen, wenn sich diese Werte in Ihrem Projekt ändern.

1
Brad Larson

Mein Arbeitsbeispiel basiert auf der Antwort von @Ben Clayton und den Kommentaren von @Luis Ascorbe und @Vahid Amiri:

Hinweis: Dieser Ansatz ändert die Datei Settings.bundle/Root.plist in der Arbeitskopie des Repositorys 

  1. Fügen Sie Ihrem Projektstamm ein Einstellungspaket hinzu. Benennen Sie es nicht um
  2. Öffnen Sie Settings.bundle/Root.plist als SourceCode 

    Ersetzen Sie den Inhalt durch:

    <?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. Fügen Sie dem Abschnitt Erstellen, Voraktionen des Projektschemas (Ziel) das folgende Skript hinzu

    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. Das aktuelle Schema erstellen und ausführen

0
Peter Kreinz

Die obigen Antworten haben bei mir nicht funktioniert, daher habe ich mein eigenes Skript erstellt.

Dadurch wird der Eintrag aus Root.plist dynamisch aktualisiert

Verwenden Sie das unten stehende Ausführungsskript. Wir arbeiten sicher verifiziert in xcode 10.3.

"var buildVersion" ist die Version, die im Titel angezeigt werden soll.

Und der Bezeichnername lautet "var version" für den Titel in 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

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