Watch: share with the complication through a Keychain group, not an App Group

Automatic signing with an App Store Connect API key registers bundle IDs and
profiles but cannot create or assign App Groups, so the archive failed. A
keychain-access-groups entry needs no portal setup. The demo flag and last
summary move into the same group; tests cover the round trip and the
migration of a pre-complication token.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
gibandClaude Opus 5.5 committed 2026-11-01 11:15:31 -05:00
1 parent 67992dbf43
commit 27469dbc77
11 files changed
+132 -49

No files matched your search

+9 -9
View File
@@ -1,22 +1,22 @@
// What the app tells the complication through the App Group's defaults: whether it is in demo mode,
// and the last summary it saw, which the complication shows when it cannot reach the gateway.
// What the app tells the complication besides the credentials: whether it is in demo mode, and the
// last summary it saw, which the complication shows when it cannot reach the gateway. Both live in
// the shared Keychain group next to the device token, the one store the two processes share.
import Foundation
enum SharedState {
private static var defaults: UserDefaults { UserDefaults(suiteName: DeviceStore.appGroup) ?? .standard }
private static let demoKey = "demo"
private static let summaryKey = "summary"
private static let demoAccount = "demo"
private static let summaryAccount = "lastSummary"
/// True while the app is in demo mode, so the complication shows the demo counts too.
static var demo: Bool {
get { defaults.bool(forKey: demoKey) }
set { defaults.set(newValue, forKey: demoKey) }
get { DeviceStore.sharedData(demoAccount) == Data([1]) }
set { DeviceStore.setSharedData(newValue ? Data([1]) : nil, account: demoAccount) }
}
/// The last summary the app or the complication saw, or nil after signing out.
static var lastSummary: Summary? {
get { defaults.data(forKey: summaryKey).flatMap { try? JSON.decoder().decode(Summary.self, from: $0) } }
set { defaults.set(newValue.flatMap { try? JSON.encoder().encode($0) }, forKey: summaryKey) }
get { DeviceStore.sharedData(summaryAccount).flatMap { try? JSON.decoder().decode(Summary.self, from: $0) } }
set { DeviceStore.setSharedData(newValue.flatMap { try? JSON.encoder().encode($0) }, account: summaryAccount) }
}
}