Versione vs build in Xcode


660

Ho un'app che ho sviluppato con Xcode 3 e che recentemente ho iniziato a modificare con Xcode 4. Nel riepilogo del target ho il modulo di destinazione dell'applicazione iOS con campi: identificatore, versione, build, dispositivi e target di distribuzione. Il campo versione è vuoto e il campo build è 3.4.0 (che corrisponde alla versione dell'app da quando stavo ancora modificando con Xcode 3).

Le mie domande sono:

  1. Qual è la differenza tra i campi versione e build?

  2. Perché il campo versione era vuoto dopo l'aggiornamento a Xcode 4?


Per prima cosa, penso che sia il numero di build che appare nell'elenco degli archivi di Xcode Organizer. A parte questo, non sono sicuro a cosa serva.
Daniel Dickison,

Risposte:


1224

Apple ha riordinato / riproposto i campi.

In futuro, se guardi la scheda Informazioni per il tuo Target applicazione, dovresti usare "Stringa di versioni del pacchetto, abbreviata" come versione (ad es. 3.4.0) e "Versione in bundle" come build (ad es. 500 o 1A500 ). Se non li vedi entrambi, puoi aggiungerli. Questi verranno associati alla casella di testo Versione e Build corretta nella scheda Riepilogo; sono gli stessi valori.

Quando si visualizza la scheda Informazioni, se si fa clic con il pulsante destro del mouse e si seleziona Mostra chiavi / valori non elaborati, i nomi effettivi sono CFBundleShortVersionString(Versione) e CFBundleVersion(Crea).

La versione di solito viene utilizzata nel modo in cui sembra che tu l'abbia utilizzata con Xcode 3. Non sono sicuro a quale livello stai chiedendo della differenza versione / build, quindi risponderò filosoficamente.

Esistono tutti i tipi di schemi, ma uno popolare è:

{MajorVersion}. {MinorVersion}. {} Revisione

  • Versione principale : principali modifiche, riprogettazioni e modifiche di funzionalità
  • Versione secondaria: miglioramenti minori, aggiunte alla funzionalità
  • Revisione : un numero di patch per la correzione di errori

Quindi la build viene utilizzata separatamente per indicare il numero totale di build per una versione o per l'intera durata del prodotto.

Molti sviluppatori iniziano il numero di build su 0 e ogni volta che creano aumentano il numero di uno, aumentando per sempre. Nei miei progetti, ho uno script che aumenta automaticamente il numero di build ogni volta che costruisco. Vedi le istruzioni per quello sotto.

  • La versione 1.0.0 potrebbe essere la build 542. Sono state necessarie 542 build per arrivare a una versione 1.0.0.
  • La versione 1.0.1 potrebbe essere build 578.
  • La versione 1.1.0 potrebbe essere build 694.
  • La versione 2.0.0 potrebbe essere build 949.

Altri sviluppatori, tra cui Apple, hanno un numero di build composto da una versione principale + versione secondaria + numero di build per il rilascio. Questi sono gli attuali numeri di versione del software, al contrario dei valori utilizzati per il marketing.

Se vai al menu Xcode > Informazioni su Xcode , vedrai i numeri di versione e build. Se premi il pulsante Altre informazioni ... vedrai un sacco di versioni diverse. Dal momento che l' Info Più ... pulsante è stato rimosso in Xcode 5, questa informazione è disponibile anche dal Software> Developer sezione del Informazioni di sistema app, disponibile aprendo di Apple di menu Strumenti> Informazioni su questo Mac > System Report ... .

Ad esempio, Xcode 4.2 (4C139). La versione di marketing 4.2 è Build 4, Build minor versione C e Build numero 139. La prossima versione (presumibilmente 4.3) sarà probabilmente Build build 4D, e il numero Build ricomincerà da 0 e aumenterà da lì.

I numeri di versione / build dell'iPhone Simulator sono identici a quelli di iPhone, Mac, ecc.

  • 3.2: (7W367a)
  • 4.0: (8A400)
  • 4.1: (8B117)
  • 4.2: (8C134)
  • 4.3: (8H7)

Aggiornamento : su richiesta, ecco i passaggi per creare uno script che viene eseguito ogni volta che si crea l'app in Xcode per leggere il numero di build, incrementarlo e riscriverlo nel {App}-Info.plistfile dell'app . Esistono ulteriori passaggi facoltativi se si desidera scrivere la versione / i numeri di build nei Settings.bundle/Root*.plistfile.

Questo è esteso dall'articolo di istruzioni qui .

In Xcode 4.2 - 5.0:

  1. Carica il tuo progetto Xcode.
  2. Nel riquadro di sinistra, fai clic sul tuo progetto nella parte superiore della gerarchia. Questo caricherà l'editor delle impostazioni del progetto.
  3. Sul lato sinistro del riquadro della finestra centrale, fai clic sulla tua app sotto l' intestazione TARGETS . Sarà necessario configurare questa configurazione per ciascun obiettivo del progetto.
  4. Seleziona la scheda Crea fasi .
    • In Xcode 4, in basso a destra, fai clic sul pulsante Aggiungi fase di generazione e seleziona Aggiungi script di esecuzione .
    • In Xcode 5, selezionare il menu Editor > Aggiungi fase di creazione > Aggiungi fase di creazione script di esecuzione .
  5. Trascina la nuova fase Esegui script per spostarla appena prima della fase Copia risorse bundle (quando il file app-info.plist verrà raggruppato con la tua app).
  6. Nella nuova Esegui script fase, impostare Shell : /bin/bash.
  7. Copia e incolla quanto segue nell'area di script per i numeri di build interi:

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

    Come sottolineato da @Bdebeez, è disponibile anche lo strumento di versioning generico di Apple ( agvtool). Se invece preferisci usarlo, allora ci sono un paio di cose da cambiare prima:

    • Seleziona la scheda Impostazioni build .
    • Nella sezione Controllo versioni , imposta la versione corrente del progetto sul numero di build iniziale che desideri utilizzare, ad esempio 1 .
    • Tornare alla scheda Fasi di generazione , trascinare e rilasciare la fase Esegui script dopo la fase Copia risorse bundle per evitare una condizione di competizione quando si tenta di creare e aggiornare il file di origine che include il numero di build.

    Nota che con il agvtoolmetodo potresti comunque ottenere periodicamente build fallite / cancellate senza errori. Per questo motivo, non è consigliabile utilizzare agvtoolcon questo script.

    Tuttavia, nella fase Esegui script , è possibile utilizzare il seguente script:

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

    L' next-versionargomento incrementa il numero di build ( bumpè anche un alias per la stessa cosa) e si -allaggiorna Info.plistcon il nuovo numero di build.

  8. E se hai un bundle Impostazioni in cui mostri la versione e la build, puoi aggiungere quanto segue alla fine dello script per aggiornare la versione e la build. Nota: modificare i PreferenceSpecifiersvalori in base alle proprie impostazioni. PreferenceSpecifiers:2significa guardare l'elemento all'indice 2 sotto l' PreferenceSpecifiersarray nel tuo file plist, quindi per un indice basato su 0, questa è la terza impostazione di preferenza nell'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

    Se stai usando agvtoolinvece di leggere Info.plistdirettamente, puoi invece aggiungere quanto segue al tuo script:

    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. E se hai un'app universale per iPad e iPhone, puoi anche configurare le impostazioni per il file iPhone:

    /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
"Nei miei progetti, ho uno script che aumenta automaticamente il numero di build ogni volta che costruisco" - puoi condividere come lo fai? grazie per i dettagli risposte e per la domanda originale.
Zsolt,

2
@Andrews - Ho aggiornato la mia risposta con i dettagli sullo script di compilazione.
Nekno,

9
Per aumentare i numeri esadecimali puoi usarebuildNumber=$(/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
In breve: HEX non è consentito nell'App Store.
Nicolas Miari,

3
(Utenti Xcode 5) Potrebbe essere necessario modificare il passaggio 5 per leggere: "Dalla barra dei menu, selezionare Editor -> Aggiungi fase di generazione -> Aggiungi fase di creazione script di esecuzione"
Greg M. Krsak,

72

(Lasciandolo qui solo per mio riferimento.) Questo mostrerà la versione e la compilazione per i campi "versione" e "build" che vedi in un target Xcode:

- (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: Hai una perdita nel tuo metodo: tu alloc/ initla stringa, che mantiene la stringa, ma non la rilasci. Su un oggetto che ritorni da un metodo, dovresti generalmente usare un metodo pratico in modo che la stringa venga automaticamente rilasciata automaticamente o chiamata autorelease. O: return [NSString stringWithFormat:@"%@ build %@", version, build]; OR return [[[NSString alloc] initWithFormat:@"%@ build %@", version, build] autorelease];
nekno,

1
Grazie @nekno, risposta modificata in modo che sia ARC o non ARC.
Dan Rosenstark,

2
Probabilmente è meglio usare le costanti ove disponibili (es. KCFBundleVersionKey), per evitare errori di battitura. Tuttavia, non sono riuscito a trovarne uno per "CFBundleShortVersionString" :)
DannyA

Hai un bug nel codice rapido - stai chiamando CFBundleShortVersionString due volte
Yariv Nissim il

Grazie @ yar1vn, l'ho risolto e NO non è al contrario.
Dan Rosenstark,

53

Il numero di build è un numero interno che indica lo stato corrente dell'app. Si differenzia dal numero di versione in quanto in genere non è rivolto all'utente e non indica alcuna differenza / funzionalità / aggiornamento come in genere farebbe un numero di versione.

Pensalo in questo modo:

  • Build ( CFBundleVersion): il numero della build. Di solito si inizia da 1 e si aumenta di 1 con ogni build dell'app. Permette rapidamente di confrontare quale build è più recente e indica il senso di progresso della base di codice. Questi possono essere estremamente preziosi quando si lavora con il QA e devono essere sicuri che i bug siano registrati con le build giuste.
  • Versione commerciale ( CFBundleShortVersionString): il numero rivolto all'utente che stai utilizzando per indicare questa versione della tua app. Di solito questo segue uno schema di versione Major.minor (ad es. MyAwesomeApp 1.2) per far sapere agli utenti quali versioni sono aggiornamenti di manutenzione più piccoli e quali sono nuove funzionalità.

Per utilizzarlo efficacemente nei tuoi progetti, Apple offre un ottimo strumento chiamato agvtool. Consiglio vivamente di utilizzare questo in quanto è MOLTO più semplice rispetto allo scripting delle modifiche plist. Ti permette di impostare facilmente sia il numero di build che la versione di marketing. È particolarmente utile durante lo scripting (ad esempio, aggiornando facilmente il numero di build su ogni build o anche interrogando quale sia il numero di build corrente). Può anche fare cose più esotiche come taggare il tuo SVN per te quando aggiorni il numero di build.

Per usarlo:

  • Imposta il tuo progetto in Xcode, in Controllo versioni, per utilizzare "Apple Generic".
  • Nel terminale
    • agvtool new-version 1 (imposta il numero di build su 1)
    • agvtool new-marketing-version 1.0 (imposta la versione Marketing su 1.0)

Vedi la pagina man di agvtoolper un sacco di buone informazioni


un altro articolo su agvtool Easy iPhone Application Versioning con agvtool
Gon

25

Lo script per aumentare automaticamente il numero di build nella risposta sopra non ha funzionato per me se il numero di build è un valore in virgola mobile, quindi l'ho modificato un po ':

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

Il numero della versione di marketing è per i clienti, chiamato numero di versione . Inizia con 1.0 e sale per i principali aggiornamenti alla 2.0 , 3.0 , per aggiornamenti minori a 1.1 , 1.2 e per correzioni di bug a 1.0.1 , 1.0.2 . Questo numero è orientato alle versioni e alle nuove funzionalità.

Il numero di build è principalmente il numero interno di build che sono state fatte fino ad allora. Ma alcuni usano altri numeri come il numero di diramazione del repository. Questo numero dovrebbe essere univoco per distinguere le diverse build quasi identiche.

Come puoi vedere, il numero di build non è necessario e dipende da te quale numero di build desideri utilizzare. Quindi, se aggiorni il tuo Xcodea una versione principale, il campo di compilazione è vuoto. Il campo della versione potrebbe non essere vuoto !.


Per ottenere il numero di build come NSStringvariabile:

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

Prendere il numero di versione come NSStringvariabile:

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

Se vuoi entrambi in uno NSString:

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

Questo è testato con Xcode versione 4.6.3 (4H1503) . Il numero di build è spesso scritto tra parentesi / parentesi graffe. Il numero di build è in esadecimale o decimale.

buildandversion


In Xcode puoi incrementare automaticamente il numero di build come numero decimale inserendo quanto segue nella Run scriptfase di build nelle impostazioni del progetto

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

Per il numero di build esadecimale, utilizzare questo script

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"

project_settings


6

Grazie a @nekno e @ ale84 per le grandi risposte.

Tuttavia, ho modificato lo script di @ ale84 in modo da aumentare leggermente i numeri di build per il virgola mobile.

il valore di incl può essere modificato in base ai requisiti del formato mobile. Ad esempio: se incl = .01, il formato di output sarebbe ... 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

Un altro modo è impostare il numero di versione in 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];
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.