Versão vs compilação no Xcode

660

Eu tenho um aplicativo que desenvolvi com o Xcode 3 e comecei a editar recentemente com o Xcode 4. No resumo do destino, tenho o formulário de destino do aplicativo iOS com os campos: identificador, versão, construção, dispositivos e destino de implantação. O campo de versão está em branco e o campo de compilação é 3.4.0 (que corresponde à versão do aplicativo de quando eu ainda estava editando com o Xcode 3).

Minhas perguntas são:

  1. Qual é a diferença entre os campos versão e construção?

  2. Por que o campo da versão estava em branco após a atualização para o Xcode 4?

chris
fonte
Por um lado, acho que é o número da compilação que aparece na lista de arquivos do Xcode Organizer. Fora isso, não sei ao certo para que é usado.
22711 Daniel Danielison

Respostas:

1224

A Apple meio que reorganizou / redirecionou os campos.

A partir de agora, se você procurar na guia Informações o seu destino de aplicativo, deverá usar a "cadeia de versões do pacote, curta" como sua versão (por exemplo, 3.4.0) e a "versão do pacote" como sua compilação (por exemplo, 500 ou 1A500 ) Se você não vir os dois, poderá adicioná-los. Esses serão mapeados para as caixas de texto Versão e compilação apropriadas na guia Resumo; eles são os mesmos valores.

Ao visualizar a guia Informações, se você clicar com o botão direito do mouse e selecionar Mostrar Chaves / Valores Brutos , verá os nomes reais CFBundleShortVersionString(Versão) e CFBundleVersion(Compilação).

A versão geralmente é usada como você parece estar usando-a com o Xcode 3. Não sei em que nível você está perguntando sobre a diferença de versão / compilação; portanto, responderei filosoficamente.

Existem todos os tipos de esquemas, mas um popular é:

{MajorVersion}. {MinorVersion}. {Revisão}

  • Versão principal - Principais alterações, reprojetos e alterações de funcionalidade
  • Versão secundária - Pequenas melhorias, adições à funcionalidade
  • Revisão - Um número de patch para correções de bugs

Em seguida, o Build é usado separadamente para indicar o número total de builds para uma liberação ou para toda a vida útil do produto.

Muitos desenvolvedores iniciam o número de compilação em 0 e, toda vez que compilam, aumentam o número em um, aumentando para sempre. Nos meus projetos, eu tenho um script que aumenta automaticamente o número da compilação toda vez que eu construo. Veja as instruções para isso abaixo.

  • A versão 1.0.0 pode ser compilada 542. Foram necessárias 542 compilações para chegar a uma versão 1.0.0.
  • A liberação 1.0.1 pode ser compilada 578.
  • A versão 1.1.0 pode ser compilada 694.
  • A versão 2.0.0 pode ser compilada 949.

Outros desenvolvedores, incluindo a Apple, têm um número de compilação composto por uma versão principal + versão secundária + número de compilações para o lançamento. Esses são os números de versão reais do software, em oposição aos valores usados ​​para o marketing.

Se você for ao menu Xcode > Sobre o Xcode , verá os números Versão e Versão. Se você pressionar o botão Mais informações ... , verá várias versões diferentes. Desde o Mais informações ... botão foi removido em Xcode 5, esta informação está também disponível a partir do Software> desenvolvedor seção do Sistema de Informação aplicativo, disponível abrindo a Apple Menu> Sobre este Mac > Relatório do sistema ... .

Por exemplo, Xcode 4.2 (4C139). A versão 4.2 do Marketing é a versão principal do Build 4, a versão secundária do C e o número 139. O próximo lançamento (provavelmente 4.3) provavelmente será o release 4D do Build, e o número do Build começará novamente em 0 e será incrementado a partir daí.

Os números de versão / versão do simulador de iPhone são da mesma maneira, assim como os iPhones, Macs etc.

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

Atualização : a pedido, aqui estão as etapas para criar um script que é executado sempre que você cria seu aplicativo no Xcode para ler o número da compilação, incrementá-lo e gravá-lo novamente no {App}-Info.plistarquivo do aplicativo . Existem etapas adicionais opcionais se você quiser gravar seus números de versão / compilação no Settings.bundle/Root*.plist(s) arquivo (s).

Isso é estendido do artigo de instruções aqui .

No Xcode 4.2 - 5.0:

  1. Carregue seu projeto do Xcode.
  2. No painel esquerdo, clique no seu projeto na parte superior da hierarquia. Isso carregará o editor de configurações do projeto.
  3. No lado esquerdo do painel da janela central, clique no seu aplicativo no cabeçalho TARGETS . Você precisará definir esta configuração para cada destino do projeto.
  4. Selecione a guia Construir fases .
    • No Xcode 4, no canto inferior direito, clique no botão Adicionar Fase de Construção e selecione Adicionar Script de Execução .
    • No Xcode 5, selecione o menu Editor > Adicionar Fase de Construção > Adicionar Fase de Construção de Script de Execução .
  5. Arraste e solte a nova fase Executar Script para movê-la imediatamente antes da fase Copiar Recursos do Pacote Configurável (quando o arquivo app-info.plist será fornecido com o aplicativo).
  6. No novo Run Script fase, definir Shell : /bin/bash.
  7. Copie e cole o seguinte na área de script para obter números inteiros de compilação:

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

    Como o @Bdebeez apontou, a Apple Generic Versioning Tool ( agvtool) também está disponível. Se você preferir usá-lo, há algumas coisas a serem alteradas primeiro:

    • Selecione a guia Configurações de compilação .
    • Na seção Versão , defina a Versão atual do projeto como o número de compilação inicial que você deseja usar, por exemplo, 1 .
    • De volta à guia Fases de Construção , arraste e solte sua fase Executar Script após a fase Copiar Recursos do Pacote para evitar uma condição de corrida ao tentar criar e atualizar o arquivo de origem que inclui seu número de construção.

    Observe que, com o agvtoolmétodo, você ainda pode periodicamente obter compilações com falha / cancelado sem erros. Por esse motivo, não recomendo usar agvtoolcom este script.

    No entanto, na fase Executar Script , você pode usar o seguinte script:

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

    O next-versionargumento incrementa o número da compilação ( bumptambém é um alias para a mesma coisa) e é -allatualizado Info.plistcom o novo número da compilação.

  8. E se você tiver um pacote configurável Configurações em que mostra a versão e a compilação, poderá adicionar o seguinte ao final do script para atualizar a versão e compilar. Nota: Altere os PreferenceSpecifiersvalores para corresponder às suas configurações. PreferenceSpecifiers:2significa olhar para o item no índice 2 sob a PreferenceSpecifiersmatriz em seu arquivo plist; portanto, para um índice baseado em 0, essa é a terceira configuração de preferência na matriz.

    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 você estiver usando, em agvtoolvez de ler Info.plistdiretamente, poderá adicionar o seguinte ao seu 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 você tiver um aplicativo universal para iPad e iPhone, também poderá definir as configurações do arquivo do 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
    
nekno
fonte
17
"Nos meus projetos, eu tenho um script que aumenta automaticamente o número da compilação toda vez que eu construo" - você pode compartilhar como fazer isso? obrigado pelos detalhes responde e pela pergunta original.
Zsolt
2
@ Andrews - Atualizei minha resposta com os detalhes no script de construção.
nekno
9
Para incrementar os números em hexadecimal você pode usarbuildNumber=$(/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
Em resumo: HEX não é permitido na AppStore.
Nicolas Miari
3
(Xcode 5 usuários) Você pode precisar alterar o passo 5 para ler: "A partir do Menu Bar, selecione Editor -> Adicionar Desenvolver Fase -> Adicionar Executar script de construção Phase"
Greg M. Krsak
72

(Apenas deixando isso aqui para minha própria referência.) Isso mostrará versão e compilação para os campos "version" e "build" que você vê em um destino do Xcode:

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

Na 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)"
}
Dan Rosenstark
fonte
2
OT: Você tem um vazamento no seu método - você alloc/ inita string, que retém a string, mas não a libera. Em um objeto que você retorna de um método, geralmente você deve usar um método de conveniência para que a sequência seja liberada automaticamente automaticamente ou chamada autorelease. Ou: return [NSString stringWithFormat:@"%@ build %@", version, build]; OR return [[[NSString alloc] initWithFormat:@"%@ build %@", version, build] autorelease];
nekno
1
Obrigado @nekno, resposta alterada, portanto é compatível com ARC ou não com ARC.
Dan Rosenstark 7/09/11
2
Provavelmente é melhor usar as constantes quando disponíveis (por exemplo, kCFBundleVersionKey), para evitar erros de digitação. No entanto, eu não consegui encontrar um para "CFBundleShortVersionString" :) #
257 DannyA
Você tem um bug no código rápida - você está chamando CFBundleShortVersionString duas vezes
Yariv Nissim
Obrigado @ yar1vn, eu consertei e NÃO, não está ao contrário.
Dan Rosenstark
53

O número da compilação é um número interno que indica o estado atual do aplicativo. Ele difere do número da versão, pois normalmente não é voltado para o usuário e não indica nenhuma diferença / recursos / atualizações, como o número da versão faria normalmente.

Pense assim:

  • Build ( CFBundleVersion): o número da build. Geralmente, você inicia isso em 1 e aumenta em 1 a cada versão do aplicativo. Ele permite rapidamente comparações de qual build é mais recente e denota o senso de progresso da base de código. Isso pode ser extremamente valioso ao trabalhar com o controle de qualidade e é necessário garantir que os erros sejam registrados nas versões corretas.
  • Versão de marketing ( CFBundleShortVersionString): o número do usuário que você está usando para indicar esta versão do seu aplicativo. Geralmente, isso segue um esquema de versão Major.minor (por exemplo, MyAwesomeApp 1.2) para permitir que os usuários saibam quais lançamentos são atualizações de manutenção menores e quais são novos recursos importantes.

Para usar isso efetivamente em seus projetos, a Apple fornece uma ótima ferramenta chamada agvtool. Eu recomendo usar isso, pois é MUITO mais simples do que fazer scripts de alterações plist. Ele permite que você defina facilmente o número da versão e a versão de marketing. É particularmente útil ao criar scripts (por exemplo, atualizar facilmente o número da compilação em cada compilação ou mesmo consultar qual é o número da compilação atual). Pode até fazer coisas mais exóticas, como marcar seu SVN quando você atualiza o número da compilação.

Para usá-lo:

  • Defina seu projeto no Xcode, em Versioning, para usar "Apple Generic".
  • No terminal
    • agvtool new-version 1 (defina o número da compilação como 1)
    • agvtool new-marketing-version 1.0 (defina a versão de marketing como 1.0)

Consulte a página de manual agvtoolpara obter muitas informações boas

Bdebeez
fonte
um outro artigo sobre agvtool o iPhone Fácil Aplicação Versioning com agvtool
Gon
25

O script para aumentar automaticamente o número da compilação na resposta acima não funcionou para mim se o número da compilação for um valor de ponto flutuante, então eu o modifiquei um pouco:

#!/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"
ale84
fonte
21

O número da liberação de marketing é para os clientes, chamado número da versão . Começa com 1.0 e sobe para as principais atualizações para 2.0 , 3.0 , para pequenas atualizações para 1.1 , 1.2 e para as correções para 1.0.1 , 1.0.2 . Esse número é orientado sobre lançamentos e novos recursos.

O número da compilação é principalmente o número interno de compilações que foram feitas até então. Mas alguns usam outros números, como o número da ramificação do repositório. Esse número deve ser exclusivo para distinguir as diferentes compilações quase iguais.

Como você pode ver, o número da compilação não é necessário e depende de você o número da compilação que deseja usar. Portanto, se você atualizar Xcodepara uma versão principal, o campo de construção estará vazio. O campo da versão pode não estar vazio!


Para obter o número da compilação como uma NSStringvariável:

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

Para obter o número da versão como uma NSStringvariável:

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

Se você quer os dois em um NSString:

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

Isso é testado com o Xcode Versão 4.6.3 (4H1503) . O número da compilação geralmente é escrito entre parênteses / chaves. O número da compilação está em hexadecimal ou decimal.

buildandversion


No Xcode, você pode incrementar automaticamente o número da compilação como um número decimal , colocando o seguinte na Run scriptfase de compilação nas configurações do projeto

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

Para número de compilação hexadecimal, use este 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

Binariano
fonte
6

Obrigado a @nekno e @ ale84 por ótimas respostas.

No entanto, modifiquei o script do @ ale84 pouco para aumentar os números de compilação para ponto flutuante.

o valor de incl pode ser alterado de acordo com seus requisitos de formato flutuante. Por exemplo: se incl = 0,01, o formato de saída seria ... 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"
iHS
fonte
1

Outra maneira é definir o número da versão em 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];
}
mark VanderWiele
fonte