Como obter a versão e o número da build de um app em Swift: explicação completa com código
\n\nVocê já se perguntou por que na App Store o mesmo aplicativo pode aparecer como "MeuApp 3.2", mas nas configurações do iPhone ele mostra "3.2.1 (45)"? Ou por que os desenvolvedores pedem o "número da build" quando você reporta um bug? A resposta é simples: dentro de cada aplicativo iOS existem dois números ocultos — a versão do aplicativo e o número da build. E hoje vamos aprender a extraí-los usando Swift. Essa é uma das perguntas mais populares no Stack Overflow (dezenas de milhares de visualizações!), e não é à toa: conhecer essas duas linhas de código pode salvar horas de depuração e evitar a frustração dos usuários.
\n\nNeste artigo, não vamos apenas copiar uma resposta do fórum. Vamos entender o que são versão e build, para que servem, como obtê-las corretamente e, o mais importante, como evitar armadilhas. Vamos nessa!
\n\nO que é versão (version) e número da build (build number)?
\n\nAntes de escrever código, vamos entender os termos. No Xcode, no arquivo Info.plist (ou nas configurações do projeto), existem duas chaves:
- \n
- CFBundleShortVersionString — é o que o usuário vê na App Store e nas configurações do aplicativo. Geralmente aparece como "1.0", "2.3.1", etc. Esta é a versão para o usuário. \n
- CFBundleVersion — é o número interno da build. Pode ser qualquer coisa: "42", "20240315", "1.0.0.123". Esta é a versão para o desenvolvedor, que ajuda a diferenciar diferentes compilações da mesma versão. \n
Por que separar? Imagine que você lançou a versão 1.0, mas encontrou um bug crítico. Você o corrige sem mudar a funcionalidade — ainda é a versão 1.0 para o usuário, mas você aumenta o número da build (por exemplo, de 1 para 2). Assim, você não confunde o usuário e, no Crashlytics, consegue ver exatamente qual build apresentou o erro.
\n\nA maneira mais simples: Bundle.main
\n\nA Apple oferece acesso fácil a esses dados através do objeto Bundle.main. Aqui está a solução clássica que você encontrará no Stack Overflow:
import UIKit\n\nclass ViewController: UIViewController {\n\n override func viewDidLoad() {\n super.viewDidLoad()\n \n // Obtém a versão do aplicativo\n let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Desconhecida"\n // Obtém o número da build\n let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "Desconhecido"\n \n print("Versão do app: \\(appVersion)")\n print("Número da build: \\(buildNumber)")\n \n // Exemplo de uso na interface\n versionLabel.text = "Versão \\(appVersion) (build \\(buildNumber))"\n }\n}\n\n\nSimples e genial. Mas vamos detalhar cada linha:
\n- \n
Bundle.main— é o bundle principal do seu aplicativo (o arquivo .app). \ninfoDictionary— um dicionário que lê oInfo.plist. \n- Usamos a conversão opcional com
as? Stringe o operador??para o caso de a chave não existir (embora seja improvável). \n
Abordagem avançada: lendo com ProcessInfo
\n\nQuer parecer um profissional? Use ProcessInfo. Essa classe sabe mais sobre o sistema do que apenas o plist. Mas para a versão do aplicativo, ela não traz nada de novo, embora possa mostrar o sistema operacional. No entanto, há um truque: se você encapsular a obtenção dos dados em uma extension, o código fica mais limpo e reutilizável.
import Foundation\n\nextension Bundle {\n var appVersion: String {\n return infoDictionary?["CFBundleShortVersionString"] as? String ?? "Desconhecida"\n }\n \n var buildNumber: String {\n return infoDictionary?["CFBundleVersion"] as? String ?? "Desconhecido"\n }\n \n var fullVersion: String {\n return "Versão \\(appVersion) (build