When I logged into my cloudkit console to inspect the database for some debugging work I couldn't access the private database. It keeps saying "failed to access iCloud data, please signi n again". No matter how many times I sign in again, whether with password or passwordless key it keeps saying the same thing. It says that message when I click on Public database, and private and shared databases are below it. I only noticed this a couple of days ago. It's done this in the past, but I eventually got back into the database but I don't know what changed to make it work.
CloudKit
RSS for tagStore structured app and user data in iCloud containers that can be shared by all users of your app using CloudKit.
Posts under CloudKit tag
200 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
I have a flutter app I developed and some of the users cannot use our backup system which uses iCloud Key-Value storage. These users all have one thing in common. Full iCloud. If they turn off the app from iCloud from backup details page in iCloud settings then it works. But if their iCloud is 100% full and they can't even access the page then it does not work.
Can someone tell me why this is happening? My app is made in flutter. It uses this package: https://pub.dev/packages/cloud_kit.
Thanks.
I get the "Permission Failure" error ("Invalid bundle ID for container") below only when running my app from my iOS Target, and not my watchkit target. The watch app is able to sync/create/delete items, but my iOS target is unable to even read the data from the cloud. The cloudkit Container ID matches my iOS Target Bundle ID, which is the apps Bundle ID.
Looking at the output of CKContainer, the container matches the iOS Bundle ID.
I have tried reseting multiple times, creating different cloud containers, reseting the Signing and Capabilites online. It always results in the same issue... What am I missing here?
<CKError 0x281b69590: "Partial Failure" (2/1011); "Failed to modify some record zones"; uuid = D57676F8-455E-4039-9DF4-824E3BAD42BE; container ID = "iCloud.companyName.AppName"; partial errors: {
com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x281b771e0: "Permission Failure" (10/2007); server message = "Invalid bundle ID for container"; op = 8CCAD43B495AADC0; uuid = D57676F8-455E-4039-9DF4-824E3BAD42BE>
}>
If one offline device increments a counter (starting at 0) value by 5 and a second offline device decrements the counter by 2, what can I do so that the final counter value is 3 (once the devices come back online)?
I have read about operational transformations for conflict resolution. Is there any example code I can look at that implements it?
I'm trying to delete many records with one CKModifyRecordsOperation and getting this error:
<CKError 0x600000dbe4f0: "Limit Exceeded" (27/1020); "Your request contains 552 items which is more than the maximum number of items in a single request (400)">
This obviously means, that Modify Operation has record limit of 400 which is equal to CKQueryOperation.maximumResults. The good solution here would be to chunk the array of records into subarrays with length less than 400 and add multiple delete operations to the database.
The only problem is that the limit for CKModifyRecordsOperation is neither documented nor provided with a constant, so it's basically a magic number.
In hope that my prayers would be heard I want to ask to add maximumResults constant to CKModifyRecordsOperation.
The hardest part of SwiftUI programming is to correctly define the layers of references that you need as your app grows features. When you add Swift data to the mix, it hard to get much of anything correct.
I have an application that interacts with the outside world via BLE and LocationManager. I need to preserve used BLE devices and then store their current state in a static Monitor type class structure. This monitor though, needs to have access to some SwiftData elements, and it is not clear from the documentation whether it's preferred to create multiple ModelContainer instances, when they might share a particular types management. This doesn't feel very safe, so it would then make more sense to have a ModelContainer stuck inside of some other static Monitor object that everyone would use to get the single ModelContainer that should be used.
All of the context specific stacking of references in SwiftUI creates huge dependency chains, and it make the build of my application, currently to take 10s of minutes sometimes, when I have changes in flux and the compiler cannot make heads or tails out of broken references.
We really need to find a way to get the compiler fixed so that as a Recursive Decent parser, it has an easier time finding a terminal state instead of crawling up and down the stack of references looking for a place that it can reach a terminal state.
Not using ';' on every statement is a big part of the problem I feel...
Afternoon all,
I am starting out and want to store data in the App, some will be user specific and some general. So I have a new developer account which should have CloudKit permissions.
I am just trying to make any of the most basic example applications work, but keep hitting issues.
I create an App, select CloudKit and SwiftData. When I go into the signing and capabilities I select the Team which has the developer account. Then the CloudKit is selected as I clicked it when creating the project, but no Container is selected. I create a Container using the +, it names it iCloud.com.mydomain.AppName. However it is coloured in Red text.
I press the refresh and then it turns into black text, the Push Notifications appear all populated for 1 second then all disappear. I have nothing under Push now, only a Trashcan button.
The Container is now selected however.
Is this an issue that the Push notifications items appeared then vanished?
When I then try to run the app, using any of the many attempts I have had with simple code samples, it always fails to create the Container, usually with an error like this:
error: Store failed to load. <NSPersistentStoreDescription: 0x600000c79ce0> (type: SQLite, url: file:///Users/cal/Library/Developer/CoreSimulator/Devices/6D2BA1B3-C7CA-499D-A280-AFF4C5E98180/data/Containers/Data/Application/B9CD5E35-08BD-44CC-A72D-EB170E3691C6/Library/Application%20Support/default.store) with error = Error Domain=NSCocoaErrorDomain Code=134060 "A Core Data error occurred." UserInfo={NSLocalizedFailureReason=CloudKit integration requires that all attributes be optional, or have a default value set. The following attributes are marked non-optional but do not have a default value:
Item: name} with userInfo {
NSLocalizedFailureReason = "CloudKit integration requires that all attributes be optional, or have a default value set. The following attributes are marked non-optional but do not have a default value:\nItem: name";
If I go into the CloudKit database view on Apple, I see the Container listed, albeit it is marked as not deployed to production.
To try to remove my newbie issues I have used many web examples, the most recent of which was the "A Beginner’s Guide to SwiftData with a to-do app" from medium.com, which should just work really, snipped from Item.swift below but I have tried several other simple examples which all give the same issue:
import Foundation
import SwiftData
@Model
class Item: Identifiable {
var name: String
init(name: String){
self.name = name
}
}
Any ideas really appreciated.
Thank you
Hello,
I have an iOS app that is still in development, and I am also making a website for it with asp.net core. I am trying to use a server to server key, but it isn't working. The response is:
{
"uuid" : "some_uuid",
"serverErrorCode" : "AUTHENTICATION_FAILED",
"reason" : "Authentication failed"
}
I am using a library called EllipticCurve. You can find it here. My code is:
var requestData = new {
zoneID = new {},
query = new {
recordType = "CD_Person",
filterBy = new [] {
new {
comparator = "EQUALS",
fieldName = "CD_email",
fieldValue = new {
value = email,
type = "String"
}
}
},
sortBy = new [] {
new {
fieldName = "CD_email"
}
}
},
zoneWide = "true",
numbersAsStrings = "true"
};
string request = JsonSerializer.Serialize(requestData);
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Apple-CloudKit-Request-KeyID", "my_key_id");
DateTime date = DateTime.Now;
string iso8601Date = date.ToUniversalTime().ToString("u").Replace(" ", "T");
client.DefaultRequestHeaders.Add("X-Apple-CloudKit-Request-ISO8601Date", iso8601Date);
byte[] bytes = Encoding.UTF8.GetBytes(request);
SHA256 hashstring = SHA256.Create();
byte[] hash = hashstring.ComputeHash(bytes);
string base64Request = Convert.ToBase64String(hash);
string paramsToSign = $"{iso8601Date}:{base64Request}:my url";
PrivateKey privateKey = PrivateKey.fromPem("-----BEGIN EC PRIVATE KEY-----\nprivate_key\n-----END EC PRIVATE KEY-----");
Signature signature = Ecdsa.sign(paramsToSign, privateKey);
client.DefaultRequestHeaders.Add("X-Apple-CloudKit-Request-SignatureV1", signature.toBase64());
var content = new StringContent(request, Encoding.UTF8, "application/json");
var response = client.PostAsync("https://api.apple-cloudkit.com/database/1/my_container/development/public/records/query", content);
string responseString = response.Result.Content.ReadAsStringAsync().Result;
Console.WriteLine(responseString);
return View();
Any help would be appreciated.
I'm building two apps. They both share a CloudKit container. One application is designed to edit the contents of the public database regardless of who a record's creator is. The other should only be allowed to read from the public database.
Since CloudKit is largely a client-side framework it's easy enough to enforce this client side.
Are there any additional guarantees that iCloud provides to enforce what the clients are signed to do? Or is there a risk of having some actor tamper with the public database that isn't using the editing application?
In my Swiftui - SwiftData based Application I get the following error after running it both on simulator and real device... The App itself runs, and all Cloudkit requirements are met on data model side. So the problem is, that it is simply no syncing to iCloud:
error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _performSetupRequest:]_block_invoke(): <NSCloudKitMirroringDelegate: 0x282648620>: Failed to set up CloudKit integration for store: <NSSQLCore: 0x10440b270> (URL: file:///var/mobile/Containers/Data/Application/731332F0-B79C-4433-AF57-875C3CC72FCD/Library/Application%20Support/default.store)
<CKError 0x28112d860: "Partial Failure" (2/1011); "Failed to modify some record zones"; uuid = 98551939-72A4-4EBB-BB0E-6E6D87DCE285; partial errors: {
com.apple.coredata.cloudkit.zone:defaultOwner = <CKError 0x281112070: "Server Rejected Request" (15/2001); "Request failed with http status code 500"; uuid = 98551939-72A4-4EBB-BB0E-6E6D87DCE285>
}>
error: CoreData+CloudKit: recoverFromError:](): - Attempting recovery from error: <CKError 0x28112d860: "Partial Failure" (2/1011); "Failed to modify some record zones"; uuid = 98551939-72A4-4EBB-BB0E-6E6D87DCE285; partial errors: {
com.apple.coredata.cloudkit.zone:defaultOwner = <CKError 0x281112070: "Server Rejected Request" (15/2001); "Request failed with http status code 500"; uuid = 98551939-72A4-4EBB-BB0E-6E6D87DCE285>
}>
error: CoreData+CloudKit: _recoverFromError:withZoneIDs:forStore:inMonitor:](): <NSCloudKitMirroringDelegate: 0x282648620> - Failed to recover from error: CKErrorDomain:15
Recovery encountered the following error: (null):0
Can anyone help me with this Problem
Thank you!
Kind Regards
Chris
Our service is 100% on token-based authentication with APNs. Each pod generates a new token to use every 30 mins. We have hundreds of pods.
We implemented this way because in Refresh your token regularly section it says
Refresh your token no more than once every 20 minutes and no less than once every 60 minutes.
APNs report an error if you use a new token more than once every 20 minutes on the same connection.
However, we saw TooManyProviderTokensUpdates sporadically. What is even stranger is, the trigger of the error does not correlate to the number of pods as we scaled up or down, nor does it correlate to the QPS. To me, it looks like It triggers randomly. Can someone from Apple shed some light on this?
My app has been in the App Store a few months. In that time I've added a few updates to my SwiftData schema using a MigrationPlan, and things were seemingly going ok. But then I decided to add CloudKit syncing. I needed to modify my models to be compatible. So, I added another migration stage for it, changed the properties as needed (making things optional or adding default values, etc.). In my tests, everything seemed to work smoothly updating from the previous version to the new version with CloudKit. So I released it to my users. But, that's when I started to see the crashes and error reports come in. I think I've narrowed it down to when users update from older versions of the app. I was finally able to reproduce this on my end, and Core Data is throwing an error when loading the ModelContainer saying "CloudKit integration requires that all attributes be optional, or have a default value set." Even though I did this in the latest schema. It’s like it’s trying to load CloudKit before performing the schema migration, and since it can’t, it just fails and won’t load anything. I’m kinda at a loss how to recover from this for these users other than tell them to delete their app and restart, but obviously they’ll lose their data that way. The only other idea I have is to setup some older builds on TestFlight and direct them to update to those first, then update to the newest production version and hope that solves it. Any other ideas? And what can I do to prevent this for future users who maybe reinstall the app from an older version too? There's nothing special about my code for loading the ModelContainer. Just a basic:
let container = try ModelContainer(
for: Foo.self, Bar.self,
migrationPlan: SchemaMigration.self,
configurations: ModelConfiguration(cloudKitDatabase: .automatic)
)
Hi,
I have recently noticed that it's taking my app a long time between the CKModifyOperations being 'completed' in the app, and for the record to actual show up through either looking at the CloudKit dashboard, or by using CKQueryOperations. The whole upload can take 10-15 minutes or more, from the time the CKOperation has completed to the time I can see all the records on the dashboard. The 'upload' seems to be happening in chunks ... for e.g. if I uploaded a 100 records, if I check after 2 minutes the query will show 20 records, and then 35-40 a bit later, and after 10+ minutes will show all 100 records (exact numbers vary of course). This was never an issue before, but has recently been reported by a couple of users of my app, and I need to know what's going on before it balloons into a big thing. And it's highly problematic, because it leads to users not being able to download the records that they uploaded on the first device.
Is there something in CloudKit servers that have changed recently? Can someone in the CloudKit team take a look? I filed a Feedback, along with CloudKit profile logs: FB13537245
I can also reproduce the issue in production as well as development environments.
Hi,
Is there some limit for how many recordIDs we can fetch in CKFetchRecordsOperation? There doesn't seem to be any batching or cursor support built in to the API. So if I pass in 5000 recordIDs, it'll work fine?
Would love to get some confirmation either ways so I can better plan for it.
Thanks!
I've been scratching my head on this one.
Out of the blue, part of my 'synchronization' mechanism that copies 'favorites' from device to device has stopped working. A user can save a favorite location and it will propagate to all of their other devices, or repopulate after an uninstall and reinstall.
My code in the space hasn't changed for months and I haven't made any schema changes to this type either. Last night I noticed the process wasn't working anymore.
My CKQueryOperation result completion is returning this error:
<CKError 0x2818a16b0: "Server Rejected Request" (15/2001); "Request failed with http status code 500"; uuid = 2CA523A6-8F39-4538-98AF-E9B7D6CACF73>
What is telling to me is that the CloudKit Console also fails with an internal error when I try to query this type in MY private database for two different accounts. I can query another type in the private database but this one won't work for two of the Apple ID's I have tried. Also interesting, if I query this type in the PUBLIC database, even though this type is only saved to the private database, that operation succeeds just fine.
I don't want to burn a DTS ticket for a server issue.
FB13543186 - CloudKit: Receiving 500 when performing a query operation on the private database
CloudKit status page is green on the developer site as of this morning.
A SwiftUI view is displaying a SwiftData model object that's being updated on another device, using CloudKit. The update arrives through CloudKit and the view is correctly updated.
However, when the view is not displaying the model object directly, but in a nested view, this nested view is NOT updated.
Why not? Is this a bug? Or is it just me, forgetting about some elementary detail?
A workaround (that I definitely don't like!) is to put a dummy SwiftData query in the nested view. Even when the dummy query result is never used, the view now IS updated correctly.
Why?
The code below is mostly Xcode's standard template for a SwiftUI+SwiftData+CloudKit app, modified to use a String property i.s.o. a Date, and to be able to edit that name in a Textfield.
The ContentView:
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@Query private var items: [Item]
var body: some View {
NavigationSplitView {
List {
ForEach(items) { item in
@Bindable var item = item
NavigationLink {
VStack(alignment: .leading) {
// item details in same view
TextField(item.name, text: $item.name)
.textFieldStyle(.roundedBorder)
.padding()
.background(.red.opacity(0.5))
// item details in nested view
ItemDetailView(item: item)
.padding()
.background(.yellow.opacity(0.5))
Spacer()
}
} label: {
Text(item.name)
}
}
.onDelete(perform: deleteItems)
}
#if os(macOS)
.navigationSplitViewColumnWidth(min: 180, ideal: 200)
#endif
.toolbar {
#if os(iOS)
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
#endif
ToolbarItem {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
}
}
} detail: {
Text("Select an item")
}
}
private func addItem() {
withAnimation {
let newItem = Item(name: "item")
modelContext.insert(newItem)
}
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
for index in offsets {
modelContext.delete(items[index])
}
}
}
}
The nested ItemDetailView:
struct ItemDetailView: View {
@Bindable var item: Item
// dummy query to force view updates triggered by CloudKit
// @Query private var items: [Item]
var body: some View {
TextField(item.name, text: $item.name)
.textFieldStyle(.roundedBorder)
}
}
The result:
Wondering if anyone else is running into this.
It seems ModelConfiguration(isStoredInMemoryOnly: true) for previews (as outlined by Paul Hudson / Hacking with Swift) works correctly for
iOS + iCloud syncing
macOS WITHOUT iCloud syncing
But as soon as I turn on iCloud syncing capability for my macOS target, its as if the isStoredInMemoryOnly has no effect on the macOS target.
Here's my code...
I made a PreviewHelper to encapsulate the preview logic...
enum PreviewHelper {
static let previewModelContainer: ModelContainer = {
do {
let config = ModelConfiguration(isStoredInMemoryOnly: true)
let container = try ModelContainer(for: Task.self, configurations: config)
return container
} catch {
fatalError("Failed to create model container for previewing: \(error.localizedDescription)")
}
}()
}
And then use it like so...
#Preview {
let container = PreviewHelper.previewModelContainer
for task in MockData.tasks {
container.mainContext.insert(task)
}
return HorizonView()
.modelContainer(container)
}
On the macOS target & destination, using a macOS device in the Preview canvas, with iCloud syncing turned on that code inserts the MockData.tasks into my iCloud container every time the preview refreshes, so the data just keeps getting duplicated. With iCloud syncing turned off it behaves as expected/correctly (just inserting the MockData as needed for Previews).
In an iOS target, using the same helper and mock data, the helper behaves as expected/correctly (with or without iCloud syncing enabled).
Assuming this might be a bug/oversight with SwiftData and macOS? Or am I missing a needed configuration/capability on the macOS side? Anybody else seeing this?
My App uses Core Data + CloudKit and requires use of CloudKit to store persistent data, that will be shared between Users. I’d like to establish the User’s identity - like so they can augment their Core Data ‘Player’ entity w/ App specific info. Certain interfaces have been deprecated (‘user discoverability’). I’ve taken to creating a ‘dummy shared zone’ and extracting the ‘owner.userIdentity':
public func establishUser () async -> User? {
let container = cloudKitContainer
// If we store the userUUID then the implication is that the `user` can
// never be deleted; that is fair enough.
let userUUIDKey = "userUUID"
var userIdentity = Optional<CKUserIdentity>.none
do {
//
// We'll store the UUID of the CoreData `User` in the CloudKit `User` record. If there
// is no UUID in CloudKit, then this will be the first time the User has ever started
// the App. We'll create a user and update the CloudKit `User` record
//
let userID = try await container.userRecordID ()
let userRecord = try await container.publicCloudDatabase.record (for: userID)
// If the `userRecord` does not have a `userUUIDKey` then we must create a new `User`.
if nil == userRecord[userUUIDKey] {
// See if the user has the required iCloud account.
let userStatus = try await container.accountStatus()
guard userStatus == .available
else {
print ("JKP: \(#function) accountStatus: \(userStatus)")
return nil
}
//
// Create a `dummyShare` (in a 'dummyZone') so we can access the share's owner
// That owner will have our `userIdentity`
//
do {
let dummyZone = CKRecordZone (zoneName: UUID().uuidString)
let dummyShare = CKShare (recordZoneID: dummyZone.zoneID)
print ("JKP: User: Establish Zone: \(dummyZone.zoneID.zoneName)")
// Save the dummyZone and then the dummyShare (for/in the dummyZone)
let _ = try await container.privateCloudDatabase.save (dummyZone)
let _ = try await container.privateCloudDatabase.save (dummyShare)
// Extract the dummyShare's owner's identity - which is 'us/me'
userIdentity = dummyShare.owner.userIdentity
// Cleanup by deleting the 'dummyShare' and then the 'dummyZone'
let _ = try await container.privateCloudDatabase.deleteRecord (withID: dummyShare.recordID)
let _ = try await container.privateCloudDatabase.deleteRecordZone (withID: dummyZone.zoneID)
}
catch {
print ("JKP: User Establish Error: \(error.localizedDescription)")
}
// Create `newUser` with the `userRecordId`. We'll use this to lookup the
// Core Data User when players appear in a League.
let newUser = User.create (context,
scope: Player.Scope.owner,
name: (userIdentity?.nameComponents ?? PersistenceController.nameDefault),
identification: userIdentity?.lookupInfo
.map { PlayerIdentification.create (lookupInfo: $0) } ?? PlayerIdentification())
… }
Is this how getting the userIdentity is meant to be done (w/o using the deprecated interfaces)? The deprecated interfaces, when warned in Xcode, reference a sample project; that project doesn’t actually use/get the userIdentity.
Also the deleteRecord and deleteRecordZone don’t appear to remove the dummy zone in CloudKit; why?
How does one know when the CloudKit data in a CoreData+CloudKit (NSPersistentCloudKitContainer) has been fully synchronized. UseCase would be a user starts the App on a second device, user deletes then reinstalls the App, another User accepts a share and the share needs to sync.
Is the containerEventChanged Notification for 'import success' the definitive event?
CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _finishedRequest:withResult:](3403): Finished request: <NSCloudKitMirroringImportRequest: 0x600002345d10> 729A742A-7F3B-42F1-B04C-72705D41FFEF with result: <NSCloudKitMirroringResult: 0x600000c4edc0> storeIdentifier: 79FA5848-A135-41B1-A36A-09F2F914D23D success: 1 madeChanges: 0 error: (null)
As the sync could be time-consuming, is there a way to identify a single CloudKit record?
I accidentally deleted about 200 records from a CloudKit database that is being used in production. Is it possible to recover these, I have no other backups of the data.