blob: 28b0826aba825c8c4d3def991d7fe3438f930cf3 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
import Foundation
import UIKit
/// Runtime app metadata read from the bundle, plus the locally-assembled
/// diagnostics used to prefill an issue report. Nothing here touches the network
/// or collects any identifier beyond the app version, iOS version, and hardware
/// model string.
enum AppInfo {
/// CFBundleShortVersionString (marketing version), falling back to the
/// compiled-in `AppVersion.current` if the Info.plist key is missing.
static var marketingVersion: String {
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? AppVersion.current
}
/// CFBundleVersion (build number).
static var buildNumber: String {
Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "—"
}
/// "5.0.0 (build 45)" — version alongside build, as the App Info row shows it.
static var versionDisplay: String {
"\(marketingVersion) (build \(buildNumber))"
}
static let minimumOS = "17.6"
static var systemVersion: String {
UIDevice.current.systemVersion
}
/// Hardware model identifier (e.g. "iPhone15,2") — a model string, not a
/// per-device identifier.
static var deviceModel: String {
var systemInfo = utsname()
uname(&systemInfo)
let identifier = withUnsafeBytes(of: &systemInfo.machine) { raw -> String in
let bytes = raw.prefix { $0 != 0 }
return String(decoding: bytes, as: UTF8.self)
}
return identifier.isEmpty ? "Unknown" : identifier
}
/// Diagnostics prefilled into an issue report. Shown to the user before any
/// send — never collected silently.
static var diagnosticsReport: String {
"""
DomainDig \(versionDisplay)
iOS \(systemVersion)
Device \(deviceModel)
"""
}
}
|