2.0: CloudKit private-database sync replaces KV snapshot sync
Foundation for 2.1 family sharing (CKShare needs these models + container). SwiftData cannot share across Apple IDs today, so 2.0 ships true multi-device sync for the same account instead: - Models made CloudKit-compatible: dropped @Attribute(.unique) on all 5, inline defaults on every attribute, WeekPlan.slots stored as optional relationship (name preserved → lightweight migration) with non-optional slotList facade; ~73 call sites renamed. - Container: cloudKitDatabase .automatic, falling back to the local-only store when CloudKit is unavailable; failures recorded to Crashlytics. - Entitlements: iCloud CloudKit service (container already existed); remote-notification background mode for push-driven sync. - Legacy KV snapshot sync (ICloudSyncService) stays inert when CloudKit is active — kept only for 1.x devices. - DeduplicationService collapses cross-device duplicates deterministically on launch (settings singleton, default tags with tagId remapping, same-week plans). - Note: AppSettings.isPremium now syncs across same-Apple-ID devices; StoreKit (PremiumSyncService + Transaction.updates) remains the source of truth and reconciles on every launch/foreground. All 21 unit tests pass, including ICloudSyncPremiumIsolationTests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BkanrydYtrme8wipTzWssG
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
5E7322F3F3624211985F2D99 /* ICloudSyncService.swift in Sources */ = {isa = PBXBuildFile; fileRef = BED090ADA1FB259AD2AFEDE2 /* ICloudSyncService.swift */; };
|
||||
5ECA2501EC257777DBE670AD /* EmptySlotView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B68E5C82608F60FF8798BB81 /* EmptySlotView.swift */; };
|
||||
6553473B007AFD04079878C6 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60F0A5C2FF1B797A4BB69B39 /* ContentView.swift */; };
|
||||
6685C591F837FAFB29A322F7 /* DeduplicationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C3CBAFE191AD6643F861B7 /* DeduplicationService.swift */; };
|
||||
670A11A9850B321D9FF76B41 /* OnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D718B2E4F7E6D22E502F0A6 /* OnboardingView.swift */; };
|
||||
6C808D1B6E8534FABC4A4053 /* WeekPlanShareView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E113A29DEC0551C41AB7EBB /* WeekPlanShareView.swift */; };
|
||||
717C67C9A7F48587667B5AE2 /* Dish.swift in Sources */ = {isa = PBXBuildFile; fileRef = 623EDDC4CD134883FC9D242D /* Dish.swift */; };
|
||||
@@ -174,6 +175,7 @@
|
||||
965555A7774FF7EB975F0A07 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
9F86EB5DDB126D73486FD956 /* MealMood.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MealMood.entitlements; sourceTree = "<group>"; };
|
||||
9FBA11C8A81D5C0CA8A3C13D /* MealWindowsStepView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MealWindowsStepView.swift; sourceTree = "<group>"; };
|
||||
A1C3CBAFE191AD6643F861B7 /* DeduplicationService.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DeduplicationService.swift; sourceTree = "<group>"; };
|
||||
A23267BAA116E1214870416C /* WeekPlan.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeekPlan.swift; sourceTree = "<group>"; };
|
||||
A3C5F7891B2D4E6F80A2C4E6 /* FeedbackStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbackStore.swift; sourceTree = "<group>"; };
|
||||
A6FC2153490D53B80DBDC034 /* WidgetDataStore.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WidgetDataStore.swift; sourceTree = "<group>"; };
|
||||
@@ -519,6 +521,7 @@
|
||||
A3C5F7891B2D4E6F80A2C4E6 /* FeedbackStore.swift */,
|
||||
71F0ADA350289AE410D572A7 /* IngredientGenerator.swift */,
|
||||
5C512046B1410E236A3F6286 /* ShoppingListService.swift */,
|
||||
A1C3CBAFE191AD6643F861B7 /* DeduplicationService.swift */,
|
||||
);
|
||||
path = Services;
|
||||
sourceTree = "<group>";
|
||||
@@ -761,6 +764,7 @@
|
||||
B8FDF31D3BD7DD7220CE21A3 /* ShoppingItem.swift in Sources */,
|
||||
44E43D5F00D1B513F9BABE80 /* ShoppingListService.swift in Sources */,
|
||||
57F1EA6B5E3AF88A61C48354 /* ShoppingListView.swift in Sources */,
|
||||
6685C591F837FAFB29A322F7 /* DeduplicationService.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user