Skip to content

Commit 73a101b

Browse files
committed
Parse new Swift Bundler additionalMetadata field when present in binary
1 parent 3c81d6e commit 73a101b

File tree

2 files changed

+47
-10
lines changed

2 files changed

+47
-10
lines changed

Sources/SwiftCrossUI/App.swift

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,24 @@ public var _forceRefresh: () -> Void = {}
3434
/// Metadata embedded by Swift Bundler if present. Loaded at app start up.
3535
private var swiftBundlerAppMetadata: AppMetadata?
3636

37+
/// An error encountered when parsing Swift Bundler metadata.
38+
private enum SwiftBundlerMetadataError: LocalizedError {
39+
case jsonNotDictionary(Any)
40+
case missingAppIdentifier
41+
case missingAppVersion
42+
43+
var errorDescription: String? {
44+
switch self {
45+
case .jsonNotDictionary:
46+
"Root metadata JSON value wasn't an object"
47+
case .missingAppIdentifier:
48+
"Missing 'appIdentifier' (of type String)"
49+
case .missingAppVersion:
50+
"Missing 'appVersion' (of type String)"
51+
}
52+
}
53+
}
54+
3755
extension App {
3856
/// Metadata loaded at app start up.
3957
public static var metadata: AppMetadata? {
@@ -78,9 +96,26 @@ extension App {
7896
let jsonData = Data(bytes[jsonStart..<lengthStart])
7997

8098
do {
81-
return try JSONDecoder().decode(
82-
AppMetadata.self,
83-
from: jsonData
99+
// Manually parsed due to the `additionalMetadata` field (which would
100+
// require a lot of boilerplate code to parse with Codable).
101+
let jsonValue = try JSONSerialization.jsonObject(with: jsonData)
102+
guard let json = jsonValue as? [String: Any] else {
103+
throw SwiftBundlerMetadataError.jsonNotDictionary(jsonValue)
104+
}
105+
guard let identifier = json["appIdentifier"] as? String else {
106+
throw SwiftBundlerMetadataError.missingAppIdentifier
107+
}
108+
guard let version = json["appVersion"] as? String else {
109+
throw SwiftBundlerMetadataError.missingAppVersion
110+
}
111+
let additionalMetadata =
112+
json["additionalMetadata"].map { value in
113+
value as? [String: Any] ?? [:]
114+
} ?? [:]
115+
return AppMetadata(
116+
identifier: identifier,
117+
version: version,
118+
additionalMetadata: additionalMetadata
84119
)
85120
} catch {
86121
print("warning: Swift Bundler metadata present but couldn't be parsed")
Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
/// Metadata loaded at app start up.
2-
public struct AppMetadata: Codable {
2+
public struct AppMetadata {
33
/// The app's reverse domain name identifier.
44
public var identifier: String
55
/// The app's version (generally a semantic version string).
66
public var version: String
7+
/// Additional developer-defined metadata.
8+
public var additionalMetadata: [String: Any]
79

8-
public init(identifier: String, version: String) {
10+
public init(
11+
identifier: String,
12+
version: String,
13+
additionalMetadata: [String: Any]
14+
) {
915
self.identifier = identifier
1016
self.version = version
11-
}
12-
13-
private enum CodingKeys: String, CodingKey {
14-
case identifier = "appIdentifier"
15-
case version = "appVersion"
17+
self.additionalMetadata = additionalMetadata
1618
}
1719
}

0 commit comments

Comments
 (0)