iCloud & Data

RSS for tag

Learn how to integrate your app with iCloud and data frameworks for effective data storage

CloudKit Documentation

Post

Replies

Boosts

Views

Activity

Increased number of CKErrorServerRejectedRequest
Hi, I have a CloudKit based app in production on the App Store for the past 5 years. One feature in the app downloads a lot of records, over a few different recordTypes, from a user's private database using an array of CKQueryOperations (using an NSOperationQueue). This has been working fine for the past few years, and even now works fine for most users, but an increasing number of users are seeing one of the operations in the array fail for CKErrorServerRejectedRequest. This has been happening over a few weeks now, and the customer support is getting burdensome. Asking the user to repeat the feature sometimes fails, and sometimes succeeds, with no obvious reason. This is also happening for operations for recordTypes where there aren't any records in the private database, as well as for recordTypes where there are hundreds of records. I haven't made any changes over the past year that directly impacts this process. Why would this sudden increase be happening and how do I go about analyzing and fixing it? Also, my current code handles this by cancelling all the operations in the operation queue, because the comment I saw in CKError.h for this error says "This is a non-recoverable error". I'm not sure I completely understand what that means ... is the operation non-recoverable (and hence I should retry by creating a new operation), or is the user's private database corrupted, or what? Would be great if I could get some insight / suggestions.
2
0
480
Oct ’23
Added new field to swiftdata model, now crashes
I had a simple class called Entry with one field (timestamp: Date) and I tried to add a new field without having to uninstall the app , so I would not crash. I tried implementing the MigrationPlan stuff but I do not know if I have to manually add a value to the new field or how exactly it works. Here is my code. When I use the EntrySchemaV0 it works fine but if I try to use the V1 it crashes. (could not fetch ModelContainer) I also tried it with a custom migration stage. Crashes with error (SwiftData/BackingData.swift:432: Fatal error: Expected only Arrays for Relationships - String) import Foundation import SwiftData enum EntrySchemaV0: VersionedSchema { static var versionIdentifier = Schema.Version(0, 1, 0) static var models: [any PersistentModel.Type] { [Entry.self] } @Model final class Entry { var timestamp: Date init(timestamp: Date) { self.timestamp = timestamp } } } enum EntrySchemaV1: VersionedSchema { static var versionIdentifier = Schema.Version(0, 2, 0) static var models: [any PersistentModel.Type] { [Entry.self] } @Model final class Entry { var name: String var timestamp: Date init(name: String = "", timestamp: Date = .now) { self.name = name self.timestamp = timestamp } } } enum EntryMigrationPlan: SchemaMigrationPlan { static var schemas: [any VersionedSchema.Type] { [EntrySchemaV0.self, EntrySchemaV1.self] } static var stages: [MigrationStage] { [migrateV0toV1] } static let migrateV0toV1 = MigrationStage.lightweight( fromVersion: EntrySchemaV0.self, toVersion: EntrySchemaV1.self ) }
3
3
951
Oct ’23
Data Migration from Development to Production in CloudKit for TestFlight Testing
I've developed an app utilizing substantial data uploaded to a CloudKit record in the development environment. Having deployed the Record Type schema to production and released a TestFlight version for testing, how can I transfer the data from the development to the production environment, or upload the data directly to the production environment? This is crucial as TestFlight testers can only access data from the production environment.
0
0
383
Oct ’23
SwiftData .returnsDistinctResults ?
With NSFetchRequest of coreData it was possible to only return distinct results from the database with .returnsDistinctResults What if any is the fetch equivalent in SwiftData ? currently I'm appending entries into a Set<String>. Only with over 200k rows and no newBackgroundContext() in SwiftData the UI is locked for a number of seconds
1
0
456
Oct ’23
Transitioning Data from Development to Production Environment in CloudKit
In order to load your data into the production environment in Apple CloudKit, follow the steps below: Deploy Your Schema: Initially, deploy your schema to the production environment using the recommended approach provided by Apple. Prepare for TestFlight: Retain all the codes and views utilized previously for uploading data to the development environment. Deploy your app to TestFlight. TestFlight Approval and Data Transition: Upon receiving approval and ensuring the functionality on TestFlight, the same codes and views that were used to upload data to the CloudKit records in the development environment will now point to the production environment. Consequently, all the data will be uploaded to the production environment, facilitating a smooth transition. Post this process, your app on TestFlight will interact with the data in the production environment of CloudKit, ensuring consistency and enabling effective testing. This method ensures a seamless transition of data from the development environment to the production environment, aligning with the operational flow of CloudKit and TestFlight.
1
0
452
Oct ’23
iCloud 503 error
Hi, our app is down since a few hours as we can not fetch data from iCloud CKErrorDescription = "Request failed with http status code 503"; CKHTTPStatus = 503; CKRetryAfter = 60; NSDebugDescription = "CKInternalErrorDomain: 2022"; NSLocalizedDescription = "Request failed with http status code 503"; NSUnderlyingError = "<CKError 0x2806784e0: "Service Unavailable" (2022); "Request failed with http status code 503"; uuid = UID; Retry after 60.0 seconds>"; RequestUUID = "UID"; } came out of nowhere.
1
0
327
Oct ’23
SwiftData - Assignment randomly failing
I have a SwiftData class which has an attribute of var dimObject : DIM? I'm trying to assign a DIM object to that attribute, buts its randomly failing with Thread 1: EXC_BAD_ACCESS (code=1, address=0x8000000000000010) Its never the same object, nor do I get any further indications of what's causing it. I've narrowed it down to digimon.dimObject = dimFound in the below function func insertDigimon(digimon: Digimon) { Thread.sleep(forTimeInterval: 1) if let dimFound = getDIMFromID(dimID: digimon.dim) { print("****************************************************************") print("Digimon: \(digimon.name) - ID: \(digimon.id)") print("DIM: \(dimFound.name)") print("Set DIM Object on Digimon") digimon.dimObject = dimFound print("Digimon object set") print("Add digimon to DIM") dimFound.addToDigimon(d: digimon) print("Digimon added to DIM") } modelContext.insert(digimon) } If I comment out that line, there's no error Both the digimon and dimFound objects aren't nil and contain the expected object.
0
1
261
Oct ’23
Core Data error: 'cannot use an attribute type of "Composite"' when "Used with CloudKit" checked
Hello, I'm running into an odd error. I'm trying to add a composite attribute called period to a Core Data Entity named Report, but I'm getting a compile-time error that points to my xcdatamodel file: Report.period cannot use an attribute type of "Composite". In my model configuration I have "Used with CloudKit" box checked. If I uncheck this box, the error goes away and everything builds fine. But the documentation for NSCompositeAttributeDescription says: You may use composite attributes anywhere you use standard attributes, including lightweight migrations and CloudKit, through NSPersistentCloudKitContainer. So it seems like I should be able to use composite attributes in Core Data with CloudKit syncing enabled. What am I missing here? Is this a bug, or am I doing something wrong?
2
0
339
Oct ’23
How can i clear bindable object.
struct AddFabButton: View { var body: some View { NavigationLink(destination: UpsertView(note: Note())){ VStack{ Image(systemName: "plus") .resizable() .scaledToFit() .frame(width: 20) .padding(.vertical, 15) .padding(.horizontal,10) } } .buttonStyle(.borderedProminent) .buttonBorderShape(.circle) .padding(.vertical,30) .padding(.horizontal) } } #Preview { AddFabButton() } // UpsertView.swift import SwiftUI import SwiftData var descriptor: FetchDescriptor<NoteBackground> { var descriptor = FetchDescriptor<NoteBackground>(sortBy: [SortDescriptor(\.createdAt)]) descriptor.fetchLimit = 1 return descriptor } struct UpsertView: View { @Environment(\.modelContext) private var modelContext @Environment(\.dismiss) var dismiss @Query(descriptor) var backgrounds: [NoteBackground] @Bindable var note: Note @State private var showBackgroundList: Bool = false @State private var selectedBackground: NoteBackground = NoteBackground(id: "0", textColor: "text") var body: some View { NavigationStack{ VStack{ VStack{ TextField("", text: $note.title, prompt: Text("Title") .foregroundStyle(Color(hex:selectedBackground.textColor).opacity(0.5)) .bold()) .foregroundStyle(Color(hex: selectedBackground.textColor)) .font(.title) .bold() ContentEditor(text: $note.content, textColor:Color(hex:selectedBackground.textColor)) } .padding() .onTapGesture { showBackgroundList = false } } .backgroundPickerList(with: $selectedBackground, isVisible: showBackgroundList) .noteItemBackground(with: selectedBackground.id ,isFullScreen: true) .animation(.easeIn(duration: 0.2), value: showBackgroundList) .frame(maxHeight: .infinity,alignment: .top) .foregroundStyle(.white) .ignoresSafeArea(.keyboard) .toolbar{ ToolbarItem(placement:.topBarTrailing){ HStack(spacing:20){ ShareNoteButton(title: note.title, content: note.content) MenuButton(iconName: "paintbrush", onPress: toggleBackgroundList, size: 20) MenuButton(iconName: "trash", onPress: onDelete, size: 20) } .padding(.horizontal) } } .onAppear{ self.selectedBackground = note.background ?? backgrounds[0] } .onChange(of: selectedBackground){ _ , newBackground in note.background = newBackground } } } } extension UpsertView{ private func toggleBackgroundList(){ showBackgroundList.toggle() } private func onDelete(){ dismiss() } private func onShare(){ } } #Preview { MainActor.assumeIsolated{ let config = ModelConfiguration(isStoredInMemoryOnly: true) let container = try! ModelContainer(for: NoteBackground.self, configurations: config) let background = NoteBackground(id: "0", image: "bird",createdAt: Date.now.addingTimeInterval(2*100)) container.mainContext.insert(background) let background2 = NoteBackground(id: "1", color: "#223233", textColor: "#000", createdAt: Date.now.addingTimeInterval(2*100)) container.mainContext.insert(background2) return NavigationStack{ UpsertView(note: Note()) } .modelContainer(container) } } after creating and save i want to clear note object I passed toUpsertView
0
0
223
Nov ’23
Persist a set of variables with SwiftData
Hi! I'm creating a document based app using DocumentGroup. I want to make persistent a set of variables that represent a certain setup of the document. I have followed the example in https://developers.apple.com/videos/play/wwdc2023/10154. If I want to implement a set of variables that define for instance the color background of a set of flashcards. How can I do it? I cannot use @Query because these set of variables is not an array. I cannot use userDefaults either because I want this set of variables to be bonded to the document and not to my application. Thank you very much for the help!
0
0
244
Nov ’23
SwiftData Schema Migration Plan when the type of a field in your model changes
Hi I am trying to figure out how to properly migrate my schema when a field in my model needs to become a different type. I start with a simple model User with an array of type String called friends @Model final class User { @Attribute(.unique) var id: String var friends: [String]? } Now I want to change the type of friends to [User]? but I am unsure how to make a migration plan for this. I created two versioned schemas enum UserSchemaV1: VersionedSchema { static var versionIdentifier = Schema.Version(1, 0, 0) static var models: [any PersistentModel.Type] { [User.self] } @Model final class User { @Attribute(.unique) var id: String var friends: [String]? } } enum UserSchemaV2: VersionedSchema { static var versionIdentifier = Schema.Version(2, 0, 0) static var models: [any PersistentModel.Type] { [User.self] } @Model final class User { @Attribute(.unique) var id: String var friends: [User]? } } Then I make a migration plan enum UsersMigrationPlan: SchemaMigrationPlan { static var stages: [MigrationStage] { [migrateV1toV2] } static var schemas: [any VersionedSchema.Type] { [UserSchemaV1.self, UserSchemaV2.self] } static let migrateV1toV2 = MigrationStage.custom( fromVersion: UserSchemaV1.self, toVersion: UserSchemaV2.self, willMigrate: nil, didMigrate: nil ) } And I make a container using my migration plan let container: ModelContainer init() { do { container = try ModelContainer(for: User.self, migrationPlan: UsersMigrationPlan.self ) } catch { fatalError("Failed to initialize user model container") } } I also use a typealias so I can keep using User in my code typealias User = UserSchemaV2.User But no matter what I try I get an error when running my code Thread 1: Fatal error: Unknown related type - User In the closure for v2 of the Schema set { _$observationRegistrar.withMutation(of: self, keyPath: \.friends) { self.setValue(forKey: \.friends, to: newValue) } } What am I misunderstanding about migrating my schema with this change? Is this something that's possible when doing a schema migration? Is there a simple/better/easier way to modify my schema to change the type of the field?
1
0
900
Nov ’23
SwiftData crashed when I insert (XCode 15.0)
Hi all, I am trying to persist some data using SwiftData, I have two models: Page Line The models are connected by a relationship like this: import SwiftData @Model final class Page { var id: UUID var created_at: Date var title: String var pinned: Bool @Relationship(deleteRule: .cascade) var lines: [Line] = [] init(id: UUID = UUID(), created_at: Date = .now, title: String = "", pinned: Bool = false) { self.id = id self.created_at = created_at self.title = title self.pinned = pinned self.lines = lines } } import SwiftData @Model final class Line: Identifiable { var id: UUID var input: String var output: String var keyword: Bool @Relationship(inverse: \Page.lines) var page: Page init(id: UUID = UUID(), input: String = "", output: String = "", keyword: Bool = false, page: Page) { self.id = id self.input = input self.output = output self.keyword = keyword self.page = page } } I attached the modelCOntainer to the Window WindowGroup { ContentView() } .modelContainer(for: Page.self) And in my ContentView I am able to query and I get an empty array: @Query(sort: [SortDescriptor(\Page.created_at, order: .reverse)], animation: .spring) var pages: [Page] However, when I try to insert a page or a line my app crashes: func addSample() { let page = Page() context.insert(page) } CrashReporter Key: 8570AF55-7ED0-39AC-F6D4-0322CC485E65 Hardware Model: Mac14,9 Process: Equals [47925] Path: /Users/USER/Library/Developer/Xcode/UserData/Previews/Simulator Devices/2652B05A-811D-4E76-8C11-833748962497/data/Containers/Bundle/Application/23A01A2A-1FB4-4A4F-A542-74637D044F4C/Equals.app/Equals Identifier: com.jonathangiardino.Equals Version: 1.0 (1) Code Type: ARM-64 (Native) Role: Foreground Parent Process: launchd_sim [43814] Coalition: com.apple.CoreSimulator.SimDevice.2652B05A-811D-4E76-8C11-833748962497 [90202] Responsible Process: SimulatorTrampoline [64001] Date/Time: 2023-11-04 17:32:37.5567 +0100 Launch Time: 2023-11-04 17:30:42.6200 +0100 OS Version: macOS 13.5 (22G74) Release Type: User Report Version: 104 Exception Type: EXC_BREAKPOINT (SIGTRAP) Exception Codes: 0x0000000000000001, 0x000000018c985be8 Termination Reason: SIGNAL 5 Trace/BPT trap: 5 Terminating Process: exc handler [47925] Triggered by Thread: 0 Kernel Triage: VM - (arg = 0x0) pmap_enter retried due to resource shortage VM - (arg = 0x0) pmap_enter retried due to resource shortage VM - (arg = 0x0) pmap_enter retried due to resource shortage Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libswiftCore.dylib 0x18c985be8 _assertionFailure(_:_:file:line:flags:) + 248 1 SwiftData 0x1a89d5724 specialized static ModelContainer.currentContainer(_:) + 692 2 SwiftData 0x1a8a4f5d0 _DefaultBackingData.init(for:) + 248 3 SwiftData 0x1a8a5419c _DefaultBackingData.__allocating_init(for:) + 52 4 SwiftData 0x1a8a11438 static PersistentModel.createBackingData<A>() + 72 5 Equals 0x1023a6e84 Page.init(id:created_at:title:pinned:) + 488 (@__swiftmacro_6Equals4Page5ModelfMm_.swift:2) 6 Equals 0x1023a6c8c Page.__allocating_init(id:created_at:title:pinned:) + 92 7 ContentView.1.preview-thunk.dylib 0x10d21181c ContentView.__preview__addSampleLine() + 256 (ContentView.swift:350) 8 ContentView.1.preview-thunk.dylib 0x10d214b6c ContentView.__preview__addNewLine() + 96 (ContentView.swift:246) 9 ContentView.1.preview-thunk.dylib 0x10d21a5b8 closure #3 in closure #1 in closure #1 in ContentView.__preview__body.getter + 36 (ContentView.swift:111) Can anyone give me a hnt of what I am doing wrong???
1
0
658
Nov ’23
The application and widget NSUbiquitousKeyValueStore sync problem
I found that the main application and widget NSUbiquitousKeyValueStore data is completely independent? (I signed in to the same iCloud account, the same AppGroup, the same iCloud Containers for the app and widget, and Key-value Storage was checked.) But when I get on the widget and modify NSUbiquitousKeyValueStore data, find the Key to the value of the same, such as in the screenshot, the main application of 'gemstone' value is 24, But the widget's value is still 0. I thought it was a synchronization problem, but using NSUbiquitousKeyValueStore.default.synchronize() or restart the App didn't solve the problem ... “Add Image”function can't used, this is the Logs: Main App Logs: ---ubiquitousKeyValueStoreDidChange ---Change reason: 0 ---The key 'experience' was updated to value '-28' ---UbiquitousKeyValueStoreDidChange: [AnyHashable("NSUbiquitousKeyValueStoreChangedKeysKey"): <__NSSingleObjectArrayI 0x280098960>( experience ) , AnyHashable("NSUbiquitousKeyValueStoreChangeReasonKey"): 0] ---ubiquitousKeyValueStoreDidChange ---Change reason: 0 ---The key 'gemstone' was updated to value '24' ---UbiquitousKeyValueStoreDidChange: [AnyHashable("NSUbiquitousKeyValueStoreChangedKeysKey"): <__NSSingleObjectArrayI 0x280081c70>( gemstone ) widget Logs: --- widget health: 0, level: 0, experience: 0 ---ubiquitousKeyValueStoreDidChange ---Change reason: 0 ---The key 'experience' was updated to value '2' ---UbiquitousKeyValueStoreDidChange: [AnyHashable("NSUbiquitousKeyValueStoreChangeReasonKey"): 0, AnyHashable("NSUbiquitousKeyValueStoreChangedKeysKey"): <__NSSingleObjectArrayI 0x159e752f0>( experience ) ] --- widget health: 0, level: 0, experience: 2 ---ubiquitousKeyValueStoreDidChange ---Change reason: 0 ---The key 'gemstone' was updated to value '2' ---UbiquitousKeyValueStoreDidChange: [AnyHashable("NSUbiquitousKeyValueStoreChangeReasonKey"): 0, AnyHashable("NSUbiquitousKeyValueStoreChangedKeysKey"): <__NSSingleObjectArrayI 0x15bb0cd80>( gemstone ) ]
2
0
410
Nov ’23
SwiftData upsert duplicates problem or ?
Context: Importing JSON to have some data during development of SwiftData MacOS app. One object is repeated several times in the JSON and each copy is in the decoded data and does get inserted into the context and can be saved to the container, but then there are multiple copies of the same object with the same identifier in the database. When I qualify If the troublesome object's class with an @Attribute(.unique) identifier then the app crashes on .save. I was expecting a silent upsert. In this case there are three @Model classes. The model has a primary object with children objects and each child may have a third object type as a property and that third object may have a distinct third object listed as one of its own properties. It is this third object which appears several times in the file since it can be associated with many children. The insert code only specifies the primary object as I was expecting nested insertion of the children and the third object. Does this need to be handled differently? I'd like to only insert the first instance of the third object and keep the relationship intact. Should upsert work on .insert and might there be a technical problem?
1
0
552
Nov ’23
CloudKit Public Database and User Access
Hello, I have a couple of questions about the CloudKit public database: Is it possible to control what authenticated users can write to the database on the server side? I know I could write logic in my iOS app to prevent to prevent certain actions, like uploading more data than I want to allow, but traditionally one would write server-side checks too. Even if I don't use CloudKit JS, it still seems like a malicious user could intercept network traffic and interact directly with iCloud to bypass any validations I've included in my app. Is it possible to block a user from using my app and interacting with CloudKit entirely? Along the same lines as question 1, I may want to block a malicious user from interacting with my public database, particularly writing to it. Is it common practice to write configuration settings to the public database as an administrative user and to have the app look for these known records? For example, I could add records to a configuration zone via the iCloud dashboard and have my app read them at startup to do things like enable/disable signups. Thanks for any help and guidance on these issues!
0
0
496
Nov ’23