cloudkit

Implement, review, or improve CloudKit and iCloud sync in iOS/macOS apps. Use when working with CKContainer, CKRecord, CKQuery, CKSubscription, CKSyncEngine, CKShare, NSUbiquitousKeyValueStore, or iCloud Drive file coordination; when syncing SwiftData models via ModelConfiguration with cloudKitDatab

By dpearson2699 · 2,804 installs

npx skills add dpearson2699/swift-ios-skills --skill cloudkit

Source repository · Upstream listing

CloudKit Sync data across devices using CloudKit, iCloud key value storage, and iCloud Drive. Covers container setup, record CRUD, queries, subscriptions, CKSyncEngine, SwiftData integration, conflict resolution, and error handling. Contents [Container and Database Setup]( container and database setup) [Workflow]( workflow) [CKRecord CRUD]( ckrecord crud) [CKQuery]( ckquery) [CKSubscription]( cksubscription) [CKSyncEngine (iOS 17+)]( cksyncengine ios 17) [SwiftData + CloudKit]( swiftdata cloudkit) [NSUbiquitousKeyValueStore]( nsubiquitouskeyvaluestore) [iCloud Drive File Sync]( icloud drive file sync) [Account Status and Error Handling]( account status and error handling) [Conflict Resolution]( conflict resolution) [Common Mistakes]( common mistakes) [Review Checklist]( review checklist) [References]( references) Workflow 1. Choose the database scope and sync owner; verify capability, container, account status, schema, and environment before writing records. 2. Make a local change durable, enqueue it, then let subscriptions or CKSyncEngine drive remote work rather than polling. 3. Persist change tokens or sync engine state after successful application. 4. Test offline edits, partial failure, rate limiting, token expiry, conflict, account loss, zone deletion, and relaunch. 5. On failure, classify the CKError , restore the affected fixture or queue item, apply the documented retry/reset/merge action, and rerun the same scenario. Never restart a full sync blindly after partial success. Load [references/cloudkit patterns.md](references/cloudkit patterns.md) for incremental zone changes, shares, assets, batch operations, and Dashboard procedures. Container and Database Setup Enable iCloud + CloudKit in Signing & Capabilities. A container provides three databases: Database Scope Requires iCloud Storage Quota Public All users Read: No, Write: Yes App quota Private Current user Yes User quota Shared Shared records Yes Owner quota CKRecord CRUD Records are key value pairs. Max 1 MB per record (excluding CKAsset data). Custom Record Zones Apps create custom zones in the private database. Shared databases expose zones that other users share with the current user. Custom zones support atomic commits, change tracking, and sharing; public databases do not support custom zones. CKQuery Query records with NSPredicate. Supported: == , != , < , , <= , = , BEGINSWITH , CONTAINS , IN , AND , NOT , BETWEEN , distanceToLocation:fromLocation: . CONTAINS tests list membership except for tokenized full text search with self CONTAINS . BEGINSWITH is the string prefix operator; unsupported operators, key paths, or field types fail when the query executes. For every encryption review, explicitly call out field eligibility: encrypted values cannot be queried or sorted; CKAsset is encrypted by default; and CKRecord.Reference cannot be encrypted because CloudKit needs it server side. CKSubscription Subscriptions trigger push notifications when records change server side. CloudKit/Xcode handles the APNs entitlement when CloudKit is enabled; no separate explicit App ID push setup is needed. Silent/background processing still needs Background Modes Remote notifications. Handle in AppDelegate: CKSyncEngine (iOS 17+) CKSyncEngine is the recommended sync approach for custom model data. It handles scheduling, transient retries, change tokens, and database subscriptions, but not app specific save failures: CKError.serverRecordChanged from sentRecordZoneChanges.failedRecordSaves still requires custom conflict resolution and rescheduling. Automatic sync timing is indeterminate. Requires CloudKit capability + Remote notifications; private/shared databases only. Key point : persist stateSerialization across launches; the engine needs it to resume from the correct change token. SwiftData + CloudKit ModelConfiguration supports CloudKit sync. In every SwiftData CloudKit implementation or review, always report two verdicts: Model compatibility : no Unique or unique constraints, optional relationships, no .deny , and external storage for large Data . Schema rollout : initialize the development schema in nonproduction builds, verify it in CloudKit Dashboard, promote it before release, and after production promotion only add schema; don't delete model types or change existing attributes. NSUbiquitousKeyValueStore Simple key value sync. Max 1024 keys, 1 MB total, 1 MB per value. Stores locally when iCloud is unavailable. iCloud Drive File Sync Use FileManager ubiquity APIs for document level sync. Call url(forUbiquityContainerIdentifier:) and setUbiquitous off the main thread; setUbiquitous performs coordinated file work and can block. If the app is presenting the file, configure an active file presenter before moving it. Monitor files with NSMetadataQuery scoped to NSMetadataQueryUbiquitousDocumentsScope or NSMetadataQueryUbiquitousDataScope . Account Status and Error Handling Always check account status before sync. Listen for .CKAccountChanged . CKError Handling Error Code Strategy .networkFailure , .networkUnavailable Queue for retry when network returns .serverRecordChanged Three way merge (see Conflict Resolution) .requestRateLimited , .zoneBusy , .serviceUnavailable Retry after retryAfterSeconds .quotaExceeded Notify user; reduce data usage .notAuthenticated Prompt iCloud sign in .partialFailure Inspect partialErrorsByItemID per item .changeTokenExpired Reset token, refetch all changes .userDeletedZone Recreate zone and re upload data Conflict Resolution When saving a record that changed server side, CloudKit returns .serverRecordChanged with three record versions. Always merge into serverRecord it has the correct change tag. Common Mistakes Mistake Fix Syncing without an account gate Check accountStatus() and model .noAccount as a user visible state. Personal data in the public database Use private scope for user data; public scope is app wide content. Timer polling Use database subscriptions or CKSyncEngine . Immediate retry after throttling Respect retryAfterSeconds and preserve pending work. Assuming the engine resolves conflicts Three way merge failedRecordSaves , then reschedule the save. Starting every fetch with a nil token Persist tokens/state; reset only on the documented expiry path. Review Checklist [ ] iCloud + CloudKit capability enabled in Signing & Capabilities [ ] Account status checked before sync; .noAccount handled gracefully [ ] Private database used for user data; public only for shared content [ ] Custom record zones created in private DB; shared DB zones discovered from shares [ ] CKError.serverRecordChanged handled with three way merge into serverRecord [ ] Network failures queued for retry; retryAfterSeconds respected [ ] CKDatabaseSubscription or CKSyncEngine used for push based sync; Remote notifications enabled for background delivery [ ] Change tokens persisted to disk; changeTokenExpired resets and refetches [ ] .partialFailure errors inspected per item via partialErrorsByItemID [ ] .userDeletedZone handled by recreating zone and resyncing [ ] SwiftData CloudKit review reports model compatibility and schema rollout: initialized/verified development schema, promoted before release, and additive only production changes [ ] NSUbiquitousKeyValueStore.didChangeExternallyNotification observed [ ] Encryption review says CKRecord.Reference cannot use encryptedValues because CloudKit needs it server side; no query/sort on encrypted fields; CKAsset is encrypted by default [ ] CKSyncEngine state serialization persisted across launches (iOS 17+) References See [references/cloudkit patterns.md](references/cloudkit patterns.md) for incremental sync, CKShare, zones, CKAsset storage, batch operations, and Dashboard usage. [CloudKit Framework](https://sosumi.ai/documentation/cloudkit) [CKContainer](https://sosumi.ai/documentation/cloudkit/ckcontainer) [CKRecord](https://sosumi.ai/documentation/cloudkit/ckrecord) [CKQuery](https://sosumi.ai/documentation/cloudkit/ckquery) [CKSubscription](https://sosumi.ai/documentation/cloudkit/cksubscription) [CKSyncEngine](https://sosumi.ai/documentation/cloudkit/cksyncengine) [CKShare](https://sosumi.ai/documentation/cloudkit/ckshare) [CKError](https://sosumi.ai/documentation/cloudkit/ckerror) [NSUbiquitousKeyValueStore](https://sosumi.ai/documentation/foundation/nsubiquitouskeyvaluestore) [SwiftData CloudKit sync](https://sosumi.ai/documentation/swiftdata/syncing model data across a persons devices)