iOS App Version and Build in Swift: A Simple Solution

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

How to Get App Version and Build Number in Swift: Full Explanation with Code

\n\n

Have you ever wondered why the same app in the App Store can be called "MyMessenger 3.2", but in the phone settings it's "3.2.1 (45)"? Or why developers ask for the "build number" when you report a bug? The answer is simple: inside every iOS app, there are two hidden numbers — app version and build number. And today we'll learn how to extract them using Swift. This is one of the most popular questions on Stack Overflow (tens of thousands of views!), and for good reason: knowing these two lines of code can save you hours of debugging and user frustration.

\n\n

In this article, we won't just copy an answer from a forum. We'll break down what version and build are, why they're needed, how to get them correctly, and most importantly, how to avoid common pitfalls. Let's go!

\n\n

What is Version and Build Number?

\n\n

Before writing code, let's clarify the terms. In Xcode, in the Info.plist file (or in project settings), there are two keys:

\n\n
    \n
  • CFBundleShortVersionString — this is what the user sees in the App Store and in the app settings. Usually looks like "1.0", "2.3.1", etc. This is the user-facing version.
  • \n
  • CFBundleVersion — this is the internal build number. It can be anything: "42", "20240315", "1.0.0.123". This is the developer-facing version that helps distinguish different builds of the same version.
  • \n
\n\n

Why separate them? Imagine you released version 1.0 but found a critical bug. You fix it without changing functionality — it's still version 1.0 for the user, but you increment the build number (e.g., from 1 to 2). This way, you don't confuse the user, and in Crashlytics you can see exactly which build crashed.

\n\n

The Simplest Way: Bundle.main

\n\n

Apple provides convenient access to this data through the Bundle.main object. Here's the classic solution you'll find on Stack Overflow:

\n\n
import UIKit\n\nclass ViewController: UIViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \n        // Get app version\n        let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown"\n        // Get build number\n        let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "Unknown"\n        \n        print("App version: \\(appVersion)")\n        print("Build number: \\(buildNumber)")\n        \n        // Example usage in UI\n        versionLabel.text = "Version \\(appVersion) (build \\(buildNumber))"\n    }\n}\n
\n\n

Simplicity at its finest. But let's break down each line:

\n
    \n
  • Bundle.main — the main bundle of your app (the .app file).
  • \n
  • infoDictionary — a dictionary that reads Info.plist.
  • \n
  • We use optional casting with as? String and the ?? operator in case the key is missing (though this is unlikely).
  • \n
\n\n

Advanced Approach: Reading from ProcessInfo

\n\n

Want to look like a pro? Use ProcessInfo. This class knows more about the system than just the plist. But for the app version, it doesn't provide anything new, though it can show the operating system. However, there's one trick: if you wrap the data retrieval in an extension, the code becomes cleaner and more reusable.

\n\n
import Foundation\n\nextension Bundle {\n    var appVersion: String {\n        return infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown"\n    }\n    \n    var buildNumber: String {\n        return infoDictionary?["CFBundleVersion"] as? String ?? "Unknown"\n    }\n    \n    var fullVersion: String {\n        return "Version \\(appVersion) (build                

Blogs

Book Recommendations