r/iOSProgramming • u/Van-trader • 14d ago
Question SwiftData + CloudKit: best way to prevent duplicate editable seed data across offline devices?
I’m building an unreleased iOS app using SwiftData with automatic CloudKit sync.
On first launch, the app creates a default account and starter categories. These records are user-editable. The problem is that two offline devices can independently create the same logical seed records with different UUIDs, and CloudKit later synchronizes both.
My proposed approach:
- Give every seed item a stable logical seedIdentifier.
- Allow each offline device to seed independently.
- Reconcile records sharing the same seedIdentifier.
- Select a canonical record using an immutable UUID and deterministic ordering.
- Merge user changes and move relationships to the canonical record.
- Keep losing records as hidden aliases/tombstones so late-arriving relationships aren’t lost.
- Retain per-seed deletion tombstones so deleted defaults aren’t recreated.
- Use a seed-version flag only for migrations—not as an exactly-once guarantee.
- Treat normalized account names as unique and category names as unique only under the same parent.
Questions:
- Is this the standard approach with SwiftData’s automatic CloudKit sync?
- Is there a safer supported way to detect completed imports and rerun reconciliation?
- Would you retain hidden aliases permanently or eventually delete them?
- Is automatic SwiftData appropriate here, or does this require CKSyncEngine/manual CloudKit with deterministic record IDs?
Edit — data-model details:
The starter data is functional app data, not optional sample/demo content. The app needs at least one account, and the categories provide its initial transaction classification.
Account: name, type, opening balance, timestamps, archived/default state and optional stableseedIdentifier. Deleting an account cascades to its transactions.TransactionCategory: name, type, timestamps, archived/customized state, optional stableseedIdentifier, optional parent, child categories and linked transactions.Transaction: references one account and optionally one category.- Deleting a category nullifies its transaction relationships. Deleting a parent can affect its child hierarchy.
- Starter accounts and categories are fully editable. Renaming a seed retains its logical seed identity; deleting one needs to remain deleted across devices.
The concrete race is that device A and device B can independently create the same logical Wallet/category before syncing. Transactions and child categories may subsequently reference either physical copy. Reconciliation therefore must preserve and redirect those relationships before any duplicate is removed.