How to use CloudKit in an iOS app
What CloudKit does for an iOS app
CloudKit gives you free, per-user cloud storage that syncs across a person's devices automatically. The private database is scoped to one Apple ID and counts against that user's iCloud quota, so your storage costs stay low. The public database is shared by everyone using the app. Because there are no keys and no separate login, CloudKit is a strong fit for apps that keep personal data, like notes, journals, or trackers, where you want sync without standing up a backend or asking users to create another account.
Adding CloudKit with AppFlight
CloudKit needs the iCloud capability and a CloudKit container turned on for the app. In AppFlight you enable iCloud for the project, and because CloudKit uses the Apple ID for auth, there is no key to classify as client or backend and nothing secret to ship. You can then ask the AI to define a record type, save a record, or run a query, and it generates the CloudKit code. If you want local persistence plus sync, you can use SwiftData with CloudKit instead and skip the CKRecord plumbing.
A SwiftUI example
Save and fetch records in the user's private database with async CloudKit:
import CloudKit
let database = CKContainer.default().privateCloudDatabase
func saveNote(_ text: String) async throws {
let record = CKRecord(recordType: "Note")
record["text"] = text as CKRecordValue
record["createdAt"] = Date() as CKRecordValue
try await database.save(record)
}
func fetchNotes() async throws -> [String] {
let query = CKQuery(
recordType: "Note",
predicate: NSPredicate(value: true)
)
query.sortDescriptors = [
NSSortDescriptor(key: "createdAt", ascending: false)
]
let (results, _) = try await database.records(matching: query)
return results.compactMap { _, result in
try? result.get()["text"] as? String
}
}
Call these from a task in your view and store the results in @State. Saved records appear on the same user's other devices once iCloud syncs.
Alternatives
SwiftData and Core Data handle local persistence and can mirror to CloudKit, so reach for those when you want offline storage plus sync without hand-writing records. Firestore and Supabase are the better choice when data is shared across accounts, needs server-side queries, or must reach users who are not signed in to iCloud. CloudKit wins for private, per-user data where zero backend and zero keys are the goal.
FAQ
Does CloudKit need an API key or backend?
No. CloudKit uses the user signed-in Apple ID for identity and runs on Apple servers, so there is no API key to embed and no backend to host. You enable the iCloud capability and a CloudKit container, and Apple handles storage and sync.
What is the difference between the private and public database?
The private database holds data scoped to one user iCloud account and counts against their iCloud storage. The public database is shared across all users of the app and counts against your app quota. Most apps use the private database for personal data.
Does CloudKit work with SwiftData or Core Data?
Yes. SwiftData can mirror a local store to CloudKit, and Core Data does the same through NSPersistentCloudKitContainer. That route gives you local persistence plus iCloud sync without writing CKRecord code by hand.