Very often you need to get basic application information, for example to show user an application version or maybe some issue has occurred and you want to collect some details about user device. Some information are relatively easy to get some are not so.

So, lets get some basic information. Personally, I prefer keep that information isolated and in one place. Lets create AppInfo struct and add couple of imports.

import SwiftUI

struct AppInfo { }

Application Information

All basic application information can be retrieved from the Bundle object directly or from it’s informational property list.

Basic Info

Display Name

static var displayName: String {
    Bundle.main.infoDictionary?["CFBundleName"] as? String ?? "Unknown"
}

Bundle Identifier

static var bundleIdentifier: String {
    return Bundle.main.bundleIdentifier ?? ""
}

Application Version

static var appVersion: String {
    Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0"
}

static var appBuild: String {
    Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "0"
}

static var appFullVersion: String {
    appVersion + "." + appBuild
}

Device Information

To get basic information about device we can use UIDevice object.

OS Version

static var systemVersion: String {
    UIDevice.current.systemVersion
}

Device Model

Unfortunately, there is no easy way to get exact device model. The UIDevice object has model property that should return device model, but it returns only device type (like iPhone). To get exact device model (like iPhone 13), we need to write a bit tricky code.

static var deviceModel: String {
#if targetEnvironment(simulator)
    let identifier = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"]!
#else
    var systemInfo = utsname()
    uname(&systemInfo)
    let machineMirror = Mirror(reflecting: systemInfo.machine)
    let identifier = machineMirror.children.reduce("") { identifier, element in
        guard let value = element.value as? Int8, value != 0 else { return identifier }
        return identifier + String(UnicodeScalar(UInt8(value)))
    }
#endif

    return identifier
}

Usage

Now, when we have everything we need we can try to use it.

Text("Version: \(AppInfo.appVersion)")

Summary

So, lets combine everything all together.

import SwiftUI

struct AppInfo {
    
    static var bundleIdentifier: String {
        return (Bundle.main.bundleIdentifier ?? "")
    }
    
    static var displayName: String {
        Bundle.main.infoDictionary?["CFBundleName"] as? String ?? "Unknown"
    }
    
    static var appBuild: String {
        Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "0"
    }
    
    static var appVersion: String {
        Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "1.0"
    }
    
    static var appFullVersion: String {
        appVersion + "." + appBuild
    }

    static var systemVersion: String {
        UIDevice.current.systemVersion
    }
    
    static var deviceModel: String {
        #if targetEnvironment(simulator)
        let identifier = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"]!
        #else
        var systemInfo = utsname()
        uname(&systemInfo)
        let machineMirror = Mirror(reflecting: systemInfo.machine)
        let identifier = machineMirror.children.reduce("") { identifier, element in
            guard let value = element.value as? Int8, value != 0 else { return identifier }
            return identifier + String(UnicodeScalar(UInt8(value)))
        }
        #endif

        return identifier
    }
}

Source Code

The sample application for this article you can find here .