Version vs Build in Xcode


660

Ich habe eine App, die ich mit Xcode 3 entwickelt und kürzlich mit der Bearbeitung mit Xcode 4 begonnen habe. In der Zielzusammenfassung habe ich das Zielformular für iOS-Anwendungen mit den Feldern: Kennung, Version, Build, Geräte und Bereitstellungsziel. Das Versionsfeld ist leer und das Erstellungsfeld ist 3.4.0 (entspricht der Version der App, als ich noch mit Xcode 3 bearbeitet habe).

Meine Fragen sind:

  1. Was ist der Unterschied zwischen den Versions- und Buildfeldern?

  2. Warum war das Versionsfeld nach dem Upgrade auf Xcode 4 leer?


Zum einen denke ich, dass es die Build-Nummer ist, die in der Archivliste von Xcode Organizer angezeigt wird. Abgesehen davon bin ich mir nicht sicher, wofür es verwendet wird.
Daniel Dickison

Antworten:


1224

Apple hat die Felder irgendwie neu angeordnet / umfunktioniert.

Wenn Sie in Zukunft auf der Registerkarte "Info" nach Ihrem Anwendungsziel suchen, sollten Sie als Version (z. B. 3.4.0) die Zeichenfolge "Bundle-Versionen, kurz" und als Build (z. B. 500 oder 1A500 "die Option" Bundle-Version "verwenden ). Wenn Sie beide nicht sehen, können Sie sie hinzufügen. Diese werden den richtigen Textfeldern für Version und Build auf der Registerkarte Zusammenfassung zugeordnet. Sie sind die gleichen Werte.

Wenn Sie auf der Registerkarte "Info" mit der rechten Maustaste klicken und " Rohschlüssel / Werte anzeigen" auswählen , werden die tatsächlichen Namen CFBundleShortVersionString(Version) und CFBundleVersion(Build) angezeigt.

Die Version wird normalerweise so verwendet, wie Sie sie anscheinend mit Xcode 3 verwendet haben. Ich bin mir nicht sicher, auf welcher Ebene Sie nach dem Unterschied zwischen Version und Build fragen, daher werde ich sie philosophisch beantworten.

Es gibt alle Arten von Schemata, aber ein beliebtes ist:

{MajorVersion}. {MinorVersion}. {Revision}

  • Hauptversion - Wichtige Änderungen, Neugestaltungen und Funktionsänderungen
  • Kleinere Version - Kleinere Verbesserungen, Ergänzungen der Funktionalität
  • Revision - Eine Patch-Nummer für Fehlerbehebungen

Anschließend wird der Build separat verwendet, um die Gesamtzahl der Builds für eine Version oder für die gesamte Produktlebensdauer anzugeben.

Viele Entwickler beginnen die Build-Nummer bei 0, und jedes Mal, wenn sie erstellen, erhöhen sie die Nummer um eins und erhöhen sich für immer. In meinen Projekten habe ich ein Skript, das die Build-Nummer bei jedem Build automatisch erhöht. Siehe Anweisungen dazu unten.

  • Release 1.0.0 könnte Build 542 sein. Es dauerte 542 Builds, um zu einem 1.0.0-Release zu gelangen.
  • Release 1.0.1 ist möglicherweise Build 578.
  • Release 1.1.0 ist möglicherweise Build 694.
  • Release 2.0.0 ist möglicherweise Build 949.

Andere Entwickler, einschließlich Apple, haben eine Build-Nummer, die aus einer Hauptversion + einer Nebenversion + einer Anzahl von Builds für die Version besteht. Dies sind die tatsächlichen Softwareversionsnummern im Gegensatz zu den für das Marketing verwendeten Werten.

Wenn Sie zu Xcode- Menü> Über Xcode gehen , werden die Versions- und Build-Nummern angezeigt. Wenn Sie auf die Schaltfläche Weitere Informationen ... klicken, werden verschiedene Versionen angezeigt. Da die Mehr Info ... Taste 5 in Xcode entfernt wurde, ist diese Information auch von der verfügbaren Software> Entwickler Abschnitt der Systeminformationen App, erhältlich durch Öffnen Apple - Menü> Über diesen Mac > System Report ... .

Zum Beispiel Xcode 4.2 (4C139). Marketing-Version 4.2 ist Build-Hauptversion 4, Build-Nebenversion C und Build-Nummer 139. Die nächste Version (vermutlich 4.3) wird wahrscheinlich Build-Version 4D sein, und die Build-Nummer beginnt bei 0 und erhöht sich von dort aus.

Die Versions- / Build-Nummern des iPhone Simulators sind genauso wie iPhones, Macs usw.

  • 3,2: (7W367a)
  • 4,0: (8A400)
  • 4,1: (8B117)
  • 4,2: (8C134)
  • 4,3: (8H7)

Update : Auf Anfrage können Sie die folgenden Schritte ausführen, um ein Skript zu erstellen, das jedes Mal ausgeführt wird, wenn Sie Ihre App in Xcode erstellen, um die Build-Nummer zu lesen, zu erhöhen und in die App- {App}-Info.plistDatei zurückzuschreiben. Es gibt optionale zusätzliche Schritte, wenn Sie Ihre Versions- / Build-Nummern in Ihre Settings.bundle/Root*.plistDatei (en) schreiben möchten .

Dies wird aus dem How-to-Artikel hier erweitert .

In Xcode 4.2 - 5.0:

  1. Laden Sie Ihr Xcode-Projekt.
  2. Klicken Sie im linken Bereich ganz oben in der Hierarchie auf Ihr Projekt. Dadurch wird der Projekteinstellungseditor geladen.
  3. Klicken Sie auf der linken Seite des mittleren Fensters auf Ihre App unter der Überschrift ZIELE . Sie müssen dieses Setup für jedes Projektziel konfigurieren.
  4. Wählen Sie die Registerkarte Build-Phasen .
    • Klicken Sie in Xcode 4 unten rechts auf die Schaltfläche Build-Phase hinzufügen und wählen Sie Run-Skript hinzufügen .
    • Wählen Sie in Xcode 5 das Menü Editor > Build-Phase hinzufügen > Run-Skript-Build-Phase hinzufügen .
  5. Ziehen Sie die neue Phase " Skript ausführen" per Drag & Drop , um sie kurz vor der Phase " Bundle-Ressourcen kopieren" zu verschieben (wenn die Datei "app-info.plist" mit Ihrer App gebündelt wird).
  6. Stellen Sie in der neuen Phase " Skript ausführen" Shell ein : /bin/bash.
  7. Kopieren Sie Folgendes und fügen Sie es in den Skriptbereich für ganzzahlige Build-Nummern ein:

    buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
    buildNumber=$(($buildNumber + 1))
    /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"

    Wie @Bdebeez hervorhob, ist auch das Apple Generic Versioning Tool ( agvtool) verfügbar. Wenn Sie es lieber verwenden möchten, müssen Sie zunächst einige Dinge ändern:

    • Wählen Sie die Registerkarte Build Settings .
    • Unter dem Versioning Abschnitt, stellen Sie die aktuelle Projektversion Sie auf die Anfangs Build - Nummer verwendet werden soll, zB 1 .
    • Zurück auf der Registerkarte " Erstellungsphasen" ziehen Sie Ihre Phase " Skript ausführen" nach der Phase " Bundle-Ressourcen kopieren" per Drag & Drop , um eine Race-Bedingung zu vermeiden, wenn Sie versuchen, die Quelldatei, die Ihre Build-Nummer enthält, sowohl zu erstellen als auch zu aktualisieren.

    Beachten Sie, dass Sie mit der agvtoolMethode möglicherweise weiterhin regelmäßig fehlerhafte / abgebrochene Builds ohne Fehler erhalten. Aus diesem Grund empfehle ich die Verwendung agvtoolmit diesem Skript nicht.

    In Ihrer Phase " Skript ausführen" können Sie jedoch das folgende Skript verwenden:

    "${DEVELOPER_BIN_DIR}/agvtool" next-version -all

    Das next-versionArgument erhöht die Build-Nummer ( bumpist auch ein Alias ​​für dasselbe) und wird mit der neuen Build-Nummer -allaktualisiert Info.plist.

  8. Wenn Sie über ein Einstellungspaket verfügen, in dem Sie die Version und den Build anzeigen, können Sie am Ende des Skripts Folgendes hinzufügen, um die Version und den Build zu aktualisieren. Hinweis: Ändern Sie die PreferenceSpecifiersWerte entsprechend Ihren Einstellungen. PreferenceSpecifiers:2bedeutet, dass Sie sich das Element in Index 2 unter dem PreferenceSpecifiersArray in Ihrer Plist-Datei ansehen. Für einen 0-basierten Index ist dies die dritte Voreinstellung im Array.

    productVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$INFOPLIST_FILE")
    /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:2:DefaultValue $buildNumber" Settings.bundle/Root.plist
    /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $productVersion" Settings.bundle/Root.plist

    Wenn Sie das verwenden, agvtoolanstatt es Info.plistdirekt zu lesen , können Sie Ihrem Skript stattdessen Folgendes hinzufügen:

    buildNumber=$("${DEVELOPER_BIN_DIR}/agvtool" what-version -terse)
    productVersion=$("${DEVELOPER_BIN_DIR}/agvtool" what-marketing-version -terse1)
    /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:2:DefaultValue $buildNumber" Settings.bundle/Root.plist
    /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $productVersion" Settings.bundle/Root.plist
  9. Wenn Sie eine universelle App für iPad und iPhone haben, können Sie auch die Einstellungen für die iPhone-Datei festlegen:

    /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:2:DefaultValue $buildNumber" Settings.bundle/Root~iphone.plist    
    /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $productVersion" Settings.bundle/Root~iphone.plist

17
"In meinen Projekten habe ich ein Skript, das die Build-Nummer bei jedem Build automatisch erhöht" - können Sie uns mitteilen, wie Sie das tun? Vielen Dank für die Details Antworten und für die ursprüngliche Frage.
Zsolt

2
@ Andrews - Ich habe meine Antwort mit den Details zum Build-Skript aktualisiert.
nekno

9
In Hex-Zahlen erhöhen können Sie verwendenbuildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE") dec=$((0x$buildNumber)) buildNumber=$(($dec + 1)) hex=$(printf "%X" $buildNumber) /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $hex" "$INFOPLIST_FILE"
Alon Amir

8
Kurzum: HEX ist im AppStore nicht erlaubt.
Nicolas Miari

3
(Xcode 5-Benutzer) Möglicherweise müssen Sie Schritt 5 ändern, um zu lesen: "
Wählen

72

(Lassen Sie dies hier nur als Referenz.) Dies zeigt die Version und den Build für die Felder "version" und "build" an, die Sie in einem Xcode-Ziel sehen:

- (NSString*) version {
    NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
    NSString *build = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
    return [NSString stringWithFormat:@"%@ build %@", version, build];
}

In Swift

func version() -> String {
    let dictionary = NSBundle.mainBundle().infoDictionary!
    let version = dictionary["CFBundleShortVersionString"] as? String
    let build = dictionary["CFBundleVersion"] as? String
    return "\(version) build \(build)"
}

2
OT: Sie haben ein Leck in Ihrer Methode - Sie alloc/ initdie Zeichenfolge, die die Zeichenfolge beibehält, aber Sie geben sie nicht frei. Für ein Objekt, das Sie von einer Methode zurückgeben, sollten Sie im Allgemeinen eine Convenience-Methode verwenden, damit die Zeichenfolge automatisch automatisch freigegeben oder aufgerufen wird autorelease. Entweder: return [NSString stringWithFormat:@"%@ build %@", version, build]; ODER return [[[NSString alloc] initWithFormat:@"%@ build %@", version, build] autorelease];
nekno

1
Danke @nekno, die Antwort wurde geändert, sodass sie ARC- oder nicht ARC-freundlich ist.
Dan Rosenstark

2
Es ist wahrscheinlich besser, die verfügbaren Konstanten (z. B. kCFBundleVersionKey) zu verwenden, um Tippfehler zu vermeiden. Allerdings konnte ich keine für "CFBundleShortVersionString" finden :)
DannyA

Sie haben einen Fehler im schnellen Code - Sie rufen CFBundleShortVersionString zweimal auf
Yariv Nissim

Danke @ yar1vn, ich habe es behoben und NEIN, es ist nicht rückwärts.
Dan Rosenstark

53

Die Build-Nummer ist eine interne Nummer, die den aktuellen Status der App angibt. Es unterscheidet sich von der Versionsnummer darin, dass es normalerweise nicht dem Benutzer zugewandt ist und keine Unterschiede / Funktionen / Upgrades anzeigt, wie dies normalerweise bei einer Versionsnummer der Fall wäre.

Stellen Sie sich das so vor:

  • Bauen (CFBundleVersion ): Die Nummer des Builds. Normalerweise beginnt man dies bei 1 und erhöht sich mit jedem Build der App um 1. Es ermöglicht schnell Vergleiche, welcher Build aktueller ist, und zeigt den Fortschritt des Fortschritts der Codebasis an. Diese können bei der Arbeit mit der Qualitätssicherung von überwältigender Bedeutung sein und sicherstellen, dass Fehler gegen die richtigen Builds protokolliert werden.
  • Marketing-Version ( CFBundleShortVersionString): Die benutzerbezogene Nummer, mit der Sie diese Version Ihrer App kennzeichnen. Normalerweise folgt dies einem Major.minor-Versionsschema (z. B. MyAwesomeApp 1.2), um den Benutzern mitzuteilen, welche Releases kleinere Wartungsupdates und welche neuen Funktionen sind.

Um dies in Ihren Projekten effektiv zu nutzen, bietet Apple ein großartiges Tool namens agvtool. Ich empfehle dringend, dies zu verwenden, da es VIEL einfacher ist, als Änderungen an der Liste vorzunehmen. Sie können auf einfache Weise sowohl die Build-Nummer als auch die Marketing-Version festlegen. Dies ist besonders nützlich bei der Skripterstellung (z. B. um die Build-Nummer bei jedem Build einfach zu aktualisieren oder sogar die aktuelle Build-Nummer abzufragen). Es kann sogar exotischere Dinge wie das Markieren Ihrer SVN für Sie tun, wenn Sie die Build-Nummer aktualisieren.

Um es zu benutzen:

  • Stellen Sie Ihr Projekt in Xcode unter Versionierung so ein, dass "Apple Generic" verwendet wird.
  • Im Terminal
    • agvtool new-version 1 (Setzen Sie die Build-Nummer auf 1)
    • agvtool new-marketing-version 1.0 (Setzen Sie die Marketing-Version auf 1.0)

Auf der Manpage von finden Sie agvtooleine Menge guter Informationen


ein weiterer Artikel über agvtool Easy iPhone Application Versioning mit agvtool
Gon

25

Das Skript zum automatischen Inkrementieren der Build-Nummer in der obigen Antwort hat bei mir nicht funktioniert, wenn die Build-Nummer ein Gleitkommawert ist. Deshalb habe ich es ein wenig geändert:

#!/bin/bash    
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
buildNumber=`echo $buildNumber +1|bc`
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"

21

Die Marketing- Versionsnummer ist für die Kunden als Versionsnummer bezeichnet . Es beginnt mit 1.0 und reicht für größere Updates auf 2.0 , 3.0 , für kleinere Updates auf 1.1 , 1.2 und für Fehlerkorrekturen auf 1.0.1 , 1.0.2 . Diese Nummer orientiert sich an Releases und neuen Funktionen.

Die Build-Nummer ist meistens die interne Anzahl der Builds , die bis dahin erstellt wurden. Einige verwenden jedoch andere Nummern wie die Zweigstellennummer des Repositorys. Diese Nummer sollte eindeutig sein , um die verschiedenen nahezu gleichen Builds zu unterscheiden.

Wie Sie sehen, ist die Build-Nummer nicht erforderlich und es liegt an Ihnen, welche Build-Nummer Sie verwenden möchten. Wenn Sie also Ihre XcodeVersion auf eine Hauptversion aktualisieren , ist das Build- Feld leer. Das Versionsfeld darf nicht leer sein!.


So erhalten Sie die Build- Nummer als NSStringVariable:

NSString * appBuildString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];

So erhalten Sie die Versionsnummer als NSStringVariable:

NSString * appVersionString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];

Wenn Sie beide in einem wollen NSString:

NSString * versionBuildString = [NSString stringWithFormat:@"Version: %@ (%@)", appVersionString, appBuildString];

Dies wird mit Xcode Version 4.6.3 (4H1503) getestet . Die Build-Nummer wird häufig in Klammern angegeben. Die Build-Nummer ist hexadezimal oder dezimal.

buildandversion


In Xcode können Sie die Build-Nummer automatisch als Dezimalzahl erhöhen, indem Sie Run scriptin den Projekteinstellungen Folgendes in die Build-Phase einfügen

#!/bin/bash    
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"

Verwenden Sie dieses Skript für die hexadezimale Build-Nummer

buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
buildNumber=$((0x$buildNumber)) 
buildNumber=$(($buildNumber + 1)) 
buildNumber=$(printf "%X" $buildNumber)
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"

Projekt Einstellungen


6

Vielen Dank an @nekno und @ ale84 für die tollen Antworten.

Ich habe jedoch das Skript von @ ale84 so geändert, dass die Build-Nummern für Gleitkommazahlen nur geringfügig erhöht werden.

Der Wert von incl kann entsprechend Ihren Anforderungen an das Floating-Format geändert werden. Zum Beispiel: Wenn inkl = .01, wäre das Ausgabeformat ... 1.19, 1.20, 1.21 ...

buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
incl=.01
buildNumber=`echo $buildNumber + $incl|bc`
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"

1

Eine andere Möglichkeit besteht darin, die Versionsnummer wie folgt festzulegen appDelegate didFinishLaunchingWithOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
     NSString * ver = [self myVersion];
     NSLog(@"version: %@",ver);

     NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
     [userDefaults setObject:ver forKey:@"version"];
     return YES;
}

- (NSString *) myVersion {
    NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
    NSString *build = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
    return [NSString stringWithFormat:@"%@ build %@", version, build];
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.