Give users access to the data your app stores on their behalf.
Framework
- Cloud
Kit
Overview
User data stored in CloudKit belongs to the user. For this reason, apps that integrate with CloudKit should give users a way to view and export their data.
Identify Containers and Record Types
To be sure that you're querying all the data stored by your app, cross-reference the list of containers your app has access to in Xcode, and assemble a list of those containers' identifiers. This process is described in Identifying an App's Containers.
The CloudKit Dashboard lists the different record types you've defined for each container in your app, as described in Create and Delete Record Types. Assemble a list of these types and make sure that each type has a queryable index on its record
field.
Associate Record Types with Containers
Associate the record types with the container they appear in. The example below uses a dictionary to represent the relationship between containers and the record types they contain.
let defaultContainer = CKContainer.default()
let documents = CKContainer(identifier: "iCloud.com.example.myexampleapp.documents")
let settings = CKContainer(identifier: "iCloud.com.example.myexampleapp.settings")
let containerRecordTypes: [CKContainer: [String]] = [
defaultContainer: ["log", "verboseLog"],
documents: ["textDocument", "spreadsheet"],
settings: ["preference", "profile"]
]
let containers = Array(containerRecordTypes.keys)
Find and List All Records
User data should be stored in a container's private database. Use the containers identified in the example above to find all record zones used in the private database for each container used by your app.
The example below shows how to iterate over the containers, zones, and records. It also shows how to list the fields for each record, which you use to show the data stored in those records.
// Utility function to display records.
// Customize it to display records appropriately
// according to your app's unique record types.
func printRecords(_ records: [CKRecord]) {
for record in records {
for key in record.allKeys() {
let value = record[key]
print(key + " = " + (value?.description ?? "") + ")")
}
}
}
for container in containers {
// User data should be stored in the private database.
let database = container.privateCloudDatabase
database.fetchAllRecordZones { zones, error in
guard let zones = zones, error == nil else {
print(error!)
return
}
// The true predicate represents a query for all records.
let alwaysTrue = NSPredicate(value: true)
for zone in zones {
for recordType in containerRecordTypes[container] ?? [] {
let query = CKQuery(recordType: recordType, predicate: alwaysTrue)
database.perform(query, inZoneWith: zone.zoneID) { records, error in
guard let records = records, error == nil else {
print("An error occurred fetching these records.")
return
}
printRecords(records)
}
}
}
}
}
Use each field's keys and values to give users an accessible report of the data your app stores in CloudKit.
Note
If your app uses CloudKit subscriptions to maintain an on-device copy of user data, you can use that copy to generate the report rather than querying CloudKit.