aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-07-24 17:51:57 -0500
committerChristian Cleberg <[email protected]>2026-07-24 18:32:24 -0500
commit0aa8cdf3bb55f31039df1ce473dc23eca22b6449 (patch)
tree50c8b44e3a66279c1761d7208a2cc146d66cd38f
parent2279dfa7c479d28b2560c1baaa13e4cf17b2eef7 (diff)
downloaddomain-dig-0aa8cdf3bb55f31039df1ce473dc23eca22b6449.tar.gz
domain-dig-0aa8cdf3bb55f31039df1ce473dc23eca22b6449.tar.bz2
domain-dig-0aa8cdf3bb55f31039df1ce473dc23eca22b6449.zip
fix: reach CloudKit instead of gating on unreliable entitlement introspection (#29)
iCloud sync always failed with "This build does not have the CloudKit entitlement required for iCloud sync." on normal Debug/device builds. `cloudKitContainer()` gated construction on `isEntitlementConfigurationAvailable()`, which inspected `Info.plist` keys and an `archived-expanded-entitlements.xcent` file. Entitlements live in the code signature, not `Info.plist`, and the `.xcent` file only exists in archived/distribution builds — so the check returned false for a correctly-signed development build, the container was never created, and every path reported `.missingEntitlement`. Stop introspecting entitlements. Always construct `CKContainer.default()` and let CloudKit's own `accountStatus()` drive availability. When the entitlement is genuinely absent, CloudKit surfaces `.missingEntitlement` / `.badContainer` / `.permissionFailure`, which `accountStatus()` now maps back to the "no entitlement" message — preserving that signal without the false negative.
-rw-r--r--DomainDig/CloudSyncService.swift53
1 files changed, 13 insertions, 40 deletions
diff --git a/DomainDig/CloudSyncService.swift b/DomainDig/CloudSyncService.swift
index 985d2a4..7e12ee6 100644
--- a/DomainDig/CloudSyncService.swift
+++ b/DomainDig/CloudSyncService.swift
@@ -336,9 +336,7 @@ final class CloudSyncService {
}
func acceptShare(metadata: CKShare.Metadata) async throws {
- guard let container = cloudKitContainer() else {
- throw CloudSyncRuntimeError.missingEntitlement
- }
+ let container = cloudKitContainer()
if metadata.participantStatus == .pending {
_ = try await container.accept(metadata)
@@ -1019,19 +1017,19 @@ final class CloudSyncService {
}
private func accountStatus() async -> AvailabilityState {
- guard let container = cloudKitContainer() else {
- return .missingEntitlement
- }
+ let container = cloudKitContainer()
return await withCheckedContinuation { continuation in
container.accountStatus { status, error in
if let error {
- let ckError = error as? CKError
- if ckError?.code == .notAuthenticated {
+ switch (error as? CKError)?.code {
+ case .notAuthenticated:
continuation.resume(returning: AvailabilityState.noAccount)
- return
+ case .missingEntitlement, .badContainer, .permissionFailure:
+ continuation.resume(returning: AvailabilityState.missingEntitlement)
+ default:
+ continuation.resume(returning: AvailabilityState.unknown)
}
- continuation.resume(returning: AvailabilityState.unknown)
return
}
@@ -1385,18 +1383,14 @@ final class CloudSyncService {
.lowercased() ?? ""
}
- private func cloudKitContainer() -> CKContainer? {
+ private func cloudKitContainer() -> CKContainer {
if let container {
return container
}
- if isEntitlementConfigurationAvailable() {
- let container = CKContainer.default()
- self.container = container
- return container
- }
-
- return nil
+ let container = CKContainer.default()
+ self.container = container
+ return container
}
private func cloudKitDatabase(in scope: SyncDatabaseScope) -> CKDatabase? {
@@ -1411,9 +1405,7 @@ final class CloudSyncService {
}
}
- guard let container = cloudKitContainer() else {
- return nil
- }
+ let container = cloudKitContainer()
switch scope {
case .privateDatabase:
@@ -1427,25 +1419,6 @@ final class CloudSyncService {
}
}
- private func isEntitlementConfigurationAvailable() -> Bool {
- if Bundle.main.object(forInfoDictionaryKey: "com.apple.developer.icloud-container-identifiers") != nil {
- return true
- }
-
- if Bundle.main.object(forInfoDictionaryKey: "com.apple.developer.ubiquity-container-identifiers") != nil {
- return true
- }
-
- if let entitlementsURL = Bundle.main.url(forResource: "archived-expanded-entitlements", withExtension: "xcent"),
- let data = try? Data(contentsOf: entitlementsURL),
- let contents = String(data: data, encoding: .utf8) {
- return contents.contains("com.apple.developer.icloud-services")
- && (contents.contains("CloudKit") || contents.contains("CloudKit-Anonymous"))
- }
-
- return false
- }
-
private var missingEntitlementMessage: String {
"This build does not have the CloudKit entitlement required for iCloud sync."
}