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

SwiftData fetch array only when i needed
I used Query(filter:sortBy:) and show them in the ListView. When I change the property of the model, because I fetched filtered and sorted array, the model immediately reflect the change and find its position. What I want is at initializing it fetches filtered and sorted array. And when I change the property nothing happens. But when I tap on refresh button, then the array should change. For example in ToDoList app, the array consists of not done works. when I tap done, it should stay until I refresh. Is it possible?
1
0
231
Apr ’24
TextField Data Saving
Hey Everyone, I am working on this project and it has to be done really soon. I have 30 TextFields and I need it to be saved to the whole app so If I had 1 phone inputting it, it would sync to another one with the same text value in it. So say I put "Done" in one TextField on Phone 1 then it'll save and update on Phone 2. Please get back to me when someone can. I have been developing in Xcode for about 7 months now and I am just running into it right now! Thanks so much
2
0
259
Apr ’24
Edit Swiftdata data
Dear all, I'm quite new to SwiftUI. I have a view where I'd like to open a sheet to edit data in a List. Here below the code of the view: import SwiftUI import SwiftData struct SettingsView: View { @Query(sort: \Stagione.idStagione) private var usoStagione: [Stagione] @Environment(\.modelContext) private var context @State private var stagione = String(Calendar.current.component(.year, from: Date())) @State private var miaSquadra = "" @State private var categoria = "" @State private var selStagione = Set<Stagione>() @State private var modificaStagione = false var body: some View { NavigationStack { GroupBox("Stagione") { Form { TextField("Stagione:", text: $stagione) .frame(width: 150) TextField("Categoria:", text: $categoria) .frame(width: 400) TextField("Mia squadra:", text: $miaSquadra) .frame(width: 400) Button("Salva") { let nuovaStagione = Stagione(idStagione: stagione, categoriaStagione: categoria, miaSquadra: miaSquadra) context.insert(nuovaStagione) miaSquadra = "" categoria = "" stagione = String(Calendar.current.component(.year, from: Date())) } .frame(maxWidth: .infinity, alignment: .trailing) .buttonStyle(.borderedProminent) .disabled(categoria.isEmpty || miaSquadra.isEmpty) } List(selection: $selStagione) { ForEach(usoStagione, id: \.self) { stag in VStack(alignment: .leading) { Text("\(stag.idStagione)").font(.title2) Text("\(stag.miaSquadra)").foregroundStyle(.secondary) Text("\(stag.categoriaStagione)").foregroundStyle(.secondary) } } .contextMenu() { Button(action: { selStagione.forEach(context.delete) }) { Text("Cancella") } Button(action: { self.modificaStagione = true }) { Text("Modifica") } } } .sheet(isPresented: $modificaStagione) { ModificaStagione(stagione: Stagione) } .listStyle(.plain) .textFieldStyle(.roundedBorder) .padding() } } .padding() .textFieldStyle(.roundedBorder) .navigationTitle("Impostazioni") GroupBox("Squadre") { } } } #Preview { SettingsView() .environmentObject(NavigationStateManager()) .modelContainer(for: Stagione.self, inMemory: true) } While here below the code of the view ModificaStagione: import SwiftUI struct ModificaStagione: View { @Environment(\.dismiss) private var dismiss let stagione: Stagione @State private var idStagione = "" @State private var categoria = "" @State private var miaSquadra = "" @State private var vistaPrecedente = true var body: some View { VStack (alignment: .leading) { GroupBox { LabeledContent { TextField("", text: $categoria) .frame(width: 400) } label: { Text("Categoria:") } LabeledContent { TextField("", text: $miaSquadra) .frame(width: 400) } label: { Text("Mia squadra:") } if modifica { Button("Aggiorna dati") { stagione.idStagione = idStagione stagione.categoriaStagione = categoria stagione.miaSquadra = miaSquadra dismiss() } .buttonStyle(.borderedProminent) } } .padding() .textFieldStyle(.roundedBorder) .navigationTitle("Modifica dati stagione") } .onAppear { idStagione = stagione.idStagione categoria = stagione.categoriaStagione miaSquadra = stagione.miaSquadra } } var modifica: Bool { categoria != stagione.categoriaStagione || miaSquadra != stagione.miaSquadra } } In the "Setting" view I receive an error message when I call the view "Modifica Stagione "saying that "Cannot convert value of type 'Stagione.Type' to expected argument type 'Stagione'". What am I doing wrong? Thanks in advance, A.
1
0
383
Apr ’24
iCloud Drive on iOS extremely slow to load and causing app issues
Previously iCloud Drive worked fine on my iPhone (15 Pro), but within the last couple of months it seems to have died. It continues to work fine on other connected devices (iPad, MBP etc), but will not work on iPhone. This issue seemed to begin roughly around the early 17.4 betas, but was also present in the public release and has continued on to the current 17.5 betas. I initially noticed WhatsApp couldn't back up to iCloud despite all the options being turned on. I assumed this was a WhatsApp issue. But I've recently noticed that Castro hangs on every single load and then crashes. I know that Castro does an initial call to iCloud to check back-ups etc so I went to have a look at iCloud Drive itself on my device - every single time I open Files, iCloud Drive takes 10-15 minutes to load/show anything. So it seems that iCloud Drive is not "holding" any information/content and is then taking an age to load, which is causing these other apps to time-out and crash. Turning off iCloud Drive on the device (a 35 minute waiting process) stops the issues and the apps work fine (aside from now not being able to back-up to iCloud as it's off), but resetting, allowing to re-sync again, does not resolve the issue on the device at all, and if it's turned back on, the apps begin to fail again, and even after a full re-sync it takes 10-15 minutes to load every time. To note; my connection is not an issue, and I have more than enough space on-device to cache/store stuff that's required. Any thoughts on what could be causing the issue and how to resolve?
1
0
663
Apr ’24
iCloud Documents content is kept during App Transfer?
Hello, we are planning to migrate an app that uses iCloud documents to store some documents that the user can upload/download and modify. In the official overview of App Transfer here, there are information related to CloudKit Containers and KVS but nothing related to iCloud Documents. The content of iCloud Documents is accessed using FileManager.default.url(forUbiquityContainerIdentifier: containerID) where the containerID has the form iCloud.com.things.things, even if in the official documentation it is written that the identifier must be prefixed with the Team ID. With this ID the storage works properly and we never experienced problems. Do you know if migrating an app with this functionality can be problematic? Do you know if the Team ID is somehow used even if not explicitly passed in the call to the function? Thank you and have a nice day!
0
0
372
Apr ’24
CloudKit notifications no longer working
I have an app that relies on CloudKit notifications for a core feature, but for about a week now the app is not receiving any CloudKit notifications. This follows a week in which I received "status 500" errors from CloudKit and my app was rendered useless. Those errors mysteriously stopped happening, but my app is still hindered by the lack of CloudKit notifications. I have not gotten any response from Apple on this, despite several attempts through various channels. It's not tenable to build apps that users rely on based on a platform that is so unreliable, and for which support is essentially nonexistent. To any CloudKit developers reading this: Please follow up with me so that I can resolve these issues for my users.
5
0
298
Apr ’24
Dependent models preview container error
I have a set of cascading dependent models. I want to create a preview container that adds them all to a preview container. I have created a model container which loads a recipe of my choice in sequentialy so the instantiation works. I noticed that everything loads but only 1 RecipeStep will ever be added. No matter how I do it, only one is added (randomly). What is the best practice for creating a swiftdata preview with dependent models? How can I put them in a struct / class for easy access? I tried making a class that initialized the whole swiftdata object however the preview crashes when using this. Note: I know one solution is that I could make child to parent fields optional, but I don't want to do that since I need them required. @Model class CocktailRecipe { @Attribute(.unique) var id: UUID @Attribute(.unique) var name: String var info: String? var menu: CocktailMenu? @Relationship(deleteRule: .cascade, inverse: \Ingredient.recipe) var ingredients: [Ingredient] @Relationship(deleteRule: .cascade, inverse: \RecipeSection.recipe) var sections: [RecipeSection] var created_at: Date init(name: String, info: String? = nil, menu: CocktailMenu? = nil, sections: [RecipeSection] = [], ingredients: [Ingredient] = []) { self.name = name self.info = info self.menu = menu self.sections = sections self.ingredients = ingredients self.created_at = Date() self.id = UUID() } } @Model class Ingredient { @Attribute(.unique) var id: UUID @Attribute(.unique) var name: String var quantity: Float? var units: IngredientUnitType var type: IngredientType var recipe: CocktailRecipe var created_at: Date init(name: String, quantity: Float? = nil, units: IngredientUnitType, type: IngredientType, recipe: CocktailRecipe) { self.name = name self.quantity = quantity self.units = units self.type = type self.recipe = recipe self.created_at = Date() self.id = UUID() } } @Model class RecipeSection { @Attribute(.unique) var id: UUID @Attribute(.unique) var title: String? @Attribute(.unique) var index: Int @Relationship(deleteRule: .cascade, inverse: \RecipeStep.section) var steps: [RecipeStep] var recipe: CocktailRecipe var created_at: Date init(title: String? = nil, recipe: CocktailRecipe, steps: [RecipeStep] = []) { self.title = title self.recipe = recipe self.index = recipe.sections.count + 1 self.steps = steps self.created_at = Date() self.id = UUID() } } @Model class RecipeStep { @Attribute(.unique) var id: UUID @Attribute(.unique) var instruction: String @Attribute(.unique) var index: Int var section: RecipeSection var created_at: Date init(instruction: String, section: RecipeSection) { self.instruction = instruction self.section = section self.index = section.steps.count + 1 self.created_at = Date() self.id = UUID() } } let cocktailPreviewContainer: ModelContainer = { do { let container = try ModelContainer( for: CocktailMenu.self, CocktailRecipe.self, Ingredient.self, RecipeSection.self, RecipeStep.self, /*Bottle.self, Bar.self, */ configurations: ModelConfiguration(isStoredInMemoryOnly: true) ) let modelContext = container.mainContext let spicyMargarita = CocktailRecipe(name: "Spicy Margarita") modelContext.insert(spicyMargarita) // Initialize ingredients let spicyMargaritaIngredients = [ Ingredient(name: "Tequila", quantity: 2, units: .ounces, type: .tequila, recipe: spicyMargarita), Ingredient(name: "Lime Juice", quantity: 1, units: .ounces, type: .mixer, recipe: spicyMargarita), Ingredient(name: "Agave Syrup", quantity: 0.5, units: .ounces, type: .mixer, recipe: spicyMargarita), // Ingredient(name: "Jalapeno", quantity: 3, units: .slices, type: .garnish, recipe: spicyMargarita) ] for ingredient in spicyMargaritaIngredients { modelContext.insert(ingredient) } try? modelContext.save() // Initialize sections and steps let preparationSection = RecipeSection(title: "title here", recipe: spicyMargarita) modelContext.insert(preparationSection) try? modelContext.save() let step1 = RecipeStep(instruction: "Muddle the jalapeno slices in the shaker.", section: preparationSection) modelContext.insert(step1) let step2 = RecipeStep(instruction: "Add tequila, lime juice, and agave syrup to shaker with ice.", section: preparationSection) modelContext.insert(step2) let step3 = RecipeStep(instruction: "Shake well.", section: preparationSection) modelContext.insert(step3) let step4 = RecipeStep(instruction: "Strain into a chilled glass.", section: preparationSection) modelContext.insert(step4) return container } catch { fatalError("Failed to create container") } }() var spicyMargarita: CocktailRecipe init() { // Initialize spicyMargarita recipe spicyMargarita = CocktailRecipe(name: "Spicy Margarita") // Initialize ingredients let tequila = Ingredient(name: "Tequila", quantity: 2, units: .ounces, type: .tequila, recipe: spicyMargarita) let limeJuice = Ingredient(name: "Lime Juice", quantity: 1, units: .ounces, type: .mixer, recipe: spicyMargarita) let agaveSyrup = Ingredient(name: "Agave Syrup", quantity: 0.5, units: .ounces, type: .mixer, recipe: spicyMargarita) let jalapeno = Ingredient(name: "Jalapeno", quantity: 3, units: .slices, type: .garnish, recipe: spicyMargarita) // Initialize sections and steps let preparationSection = RecipeSection(recipe: spicyMargarita) let preparationSteps = [ RecipeStep(instruction: "Muddle the jalapeno slices in the shaker.", section: preparationSection), RecipeStep(instruction: "Add tequila, lime juice, and agave syrup to shaker with ice.", section: preparationSection), RecipeStep(instruction: "Shake well.", section: preparationSection), RecipeStep(instruction: "Strain into a chilled glass.", section: preparationSection) ] // WHEN THE BELOW IS COMMENTED OUT, no errors, but have many missing objects. spicyMargarita.ingredients.append(contentsOf: [tequila, limeJuice, agaveSyrup, jalapeno]) spicyMargarita.sections.append(preparationSection) preparationSection.steps.append(contentsOf: preparationSteps)
0
0
142
Apr ’24
Advantages Of SwiftData
What sets the SwiftData framework apart from traditional iOS data storage solutions like Core Data or Realm? Could you elaborate on SwiftData's unique features and architecture that enable developers to efficiently manage data in their Swift projects? How does SwiftData enhance the development experience by seamlessly integrating with Swift's language features and paradigms
3
0
388
Apr ’24
SwiftData, Core Data, and initializing CloudKit development Schema
I recently discovered the new documentation for enabling CloudKit sync with SwiftData. A key step I was missing in my previous setup was this step: Initialize the CloudKit development schema. When I run this though, I get Core Data errors in my log... CoreData: Unsupported attribute type I've noticed that it seems to be preventing adding fields for my model properties that are Codable structs. I've been able to add Codable structs to my SwiftData models synced with CloudKit before. But using Core Data to initialize the CloudKit schema like the documentation suggests just doesn't work. Is there some other way around this? I'm about to just give up on CloudKit sync altogether. I need this to work because I'm trying to add some new fields and populate the fields with data based on existing data during the migration, but this seems to be preventing migration completely. If I don't initialize the schema, I get different errors and the ModelContainer won't initialize at all.
2
1
412
Apr ’24
CloudKit - Cannot create or modify field 'CD_nameFirstChar' in record 'CD_Charts' in production schema
Some of my users are reporting an inability to sync via CloudKit between devices. I have not seen it on any of my devices, but one user got me some console logs that are showing the following error: <CKError 0x600000a0f840: "Partial Failure" (2/1011); "Failed to modify some records"; uuid = EDC7B3E3-02F8-43B7-83B6-22D17EF0442A; container ID = "iCloud.cribaudo.iphemeris"; partial errors: { C611E11F-3DC0-484C-8FC1-23473062D9D0:(com.apple.coredata.cloudkit.zone:defaultOwner) = <CKError 0x600000a04660: "Invalid Arguments" (12/2006); server message = "Cannot create or modify field 'CD_nameFirstChar' in record 'CD_Charts' in production schema"; op = D83EF1F7DD772042; uuid = EDC7B3E3-02F8-43B7-83B6-22D17EF0442A> I do not understand this: The field CD_nameFirstChar was added to the data model in the version 15. Automatic Migration is enabled. The CloudKit Console says the Private Database Container being used by my App is deployed to production. The entity CD_Charts (I only have one) that is deployed to production shows that field as present (CD_nameFirstChar). Why would this user be getting this error? As far as I can see they are running a version where migration to Model 15 should have been triggered at some point in the past. If somehow something went wrong with their migration, how would I fix it? Any thoughts / ideas are appreciated. One thing I should add is that the migration from Model 14 to 15 was not lightweight. I did use: @interface ModelMigration14to15 : NSEntityMigrationPolicy -(NSString *)nameFirstChar:(NSString *)name; @end And I used a MapModel14to15 which used the above function to set the value of nameFirstChar. The Value Expression for that attribute is: FUNCTION($entityPolicy,` "nameFirstChar:" , $source.name) from the above mentioned NSEntityMigrationPolicy class. This worked ok on all my devices and apparently on some user devices. This issues seems to effect only a small subset of my users but not all? So I am at a loss to understand why this would happen or how to fix it.
2
0
405
Apr ’24
Renaming Core Data Entities - colliding with Animation's Transaction
Porting some Core Data code that was written several years ago. It has an entity called Transaction. This pre-dates Transaction that appeared in Animation. So Apple is now colliding with my naming. Looks like light weight migration isn't going to do the trick and I need to do more work for migration to work. Checking whether there is some magical use of namespace where I could separate my entity use of Transaction. Or it's full weight migration...
0
0
285
Apr ’24
SwiftData - Insert and delete
Hi, I started a new project selecting SwiftData as db by default. I created my models as default. @Model class Trip { var id: UUID public private(set) var Name: String public private(set) var Members: [Member] public private(set) var Buys: [Buy] public func removeBuy(indexBuyToRemove: Int) { self.Buys.remove(at: indexBuyToRemove) } } @Model class Member: Identifiable, Equatable { var id: UUID public private(set) var Name: String } @Model class Buy: Identifiable, Equatable { var id: UUID public private(set) var Author: Member public private(set) var Ammount: Double public private(set) var Title: String } I initialize my trips as this in my ContentView @Query public var tripsList: [Trip] And then pass this list in every other view. I also have a ModelContext as default, passed like this in the @Main @main struct MainApp: App { var sharedModelContainer: ModelContainer = { let schema = Schema([ Member.self, Buy.self, Trip.self ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) do { return try ModelContainer(for: schema, configurations: [modelConfiguration]) } catch { fatalError("Could not create ModelContainer: \(error)") } }() var body: some Scene { WindowGroup { ContentView() .preferredColorScheme(.dark) } .modelContainer(sharedModelContainer) } } And defining in the other views like this @Environment(\.modelContext) var modelContext Now. For the problem of consistency. Whenever I add a new Trip I do this or delete (as .onDelete in the List) public func addTrip(Trip: Trip) { modelContext.insert(Trip) } private func deleteItems(offsets: IndexSet) { withAnimation { for index in offsets { modelContext.delete(tripsList[index]) } } } And everything works fine. The problem starts when I try to delete a Buy element of the Trip.Buys: [Buy]. I do like this: private func deleteItems(offsets: IndexSet) { withAnimation { for index in offsets { let buyToRemove = trip.Buys[index] trip.removeBuy(indexBuyToRemove: index) do { try modelContext.save() } catch {} } } } The delete is not consistent. What am I missing? What am I doing wrong? Thank you for your help
0
0
244
Apr ’24
CloudKit database errors: "request failed with http status code 500"
Since a couple days ago, CloudKit database queries in my app and on the CloudKit dashboard fail with the error "request failed with http status code 500". Nothing significant changed in the app recently, and it has otherwise worked well most of the time for more than a year, although CloudKit seems to have outages somewhat frequently. My app is mostly unusable without access to the CloudKit database, so this is a critical issue. I have also filed a Feedback report (FB13709321) on this issue.
1
0
327
Apr ’24
CKSyncEngine - Are the "change batches" we send to iCloud guaranteed to be identical to the batches iCloud sends back to other devices?
Hey, I'm currently working on adding CloudKit support to the GRDB SQLite database in my app. CKSyncEngine, though still a bit tricky to wrap your head around, is amazing! I have most of the basic setup implemented and some very easy cases already work, which is really exciting! However, I do have some questions regarding data consistency across devices. I'm not sure though, that these questions are actually "correct" to ask. Maybe my entire approach is inherently flawed. Say we add two records to the pending changes of the sync engine: // I'm simplifying CKRecord.ID to be a String here syncEngine.state.add(pendingRecordZoneChanges: [.saveRecord("1"), .saveRecord("2")] Let's also say that both records are tightly connected. For example, they could be in a one-to-one relationship and must always be added to the database together because the app relies on the existence of either none or both. After that call, at some later point, the system will call the sync engine's delegate nextRecordZoneChangeBatch(_:syncEngine:) for us to batch the changes together to send to iCloud. First question: Can we guarantee that records "1" and "2" always land in the exact same batch, and are never separated? Looking at the example code, there are two line that worry me a bit: // (Sample project: `SyncedDatabase.swift, lines 132-133`) let scope = context.options.scope let changes = syncEngine.state.pendingRecordZoneChanges.filter { scope.contains($0) } The scope could lead to one of the two records being filtered out. However, my assumption is that the scope will always be .all when the system calls it from an automatically managed schedule, and only differs when you manually specify a different value through calling syncEngine.sendChanges(_:). Is that correct? Now back to the example. Say we successfully batched records "1" and "2" together and the changes have been sent to iCloud. Awesome! What happens next? Other connected devices will, at some point, fetch those changes and apply them to their respective local databases. Second question: Can we guarantee that iCloud sends the exact same batches from earlier to other devices and does not create new batches from all the changes? I'm worried that iCloud might take all stored changes and "re-batch" them for whatever reason (efficiency, for example). Because that could cause records "1" and "2" to be separated into different batches. A second device could end up receiving "1" and, for at least some period of time, will not receive "2", which would be an "illegal" state of the data. I'd appreciate any help or clarification on this :) Thanks a lot!
2
0
326
Apr ’24
Core data crashing on _sharedIMPL_setvfk_core
Hello I have a TestFlight tester getting a random repeated crash when the app is interacting with core data. Every time it crashes we get the call stack like below from line 6 stating -NSManagedObject _processRecentChanges. Searching for _sharedIMPL_setvfk_core it seems to indicate a multithreading issue but my managedObjectContext is initialized with main queue concurrency. - (NSManagedObjectContext *)managedObjectContext { if (managedObjectContext != nil) { return managedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType: NSMainQueueConcurrencyType]; [managedObjectContext setPersistentStoreCoordinator:coordinator]; } return managedObjectContext; } When I pulled the cashpoint in to the Xcode project everything appears to be running on the main thread. I can't seem to find documentation on what might be causing the issue. Any pointers would be appreciated. The app is compiled on Xcode 15 targeting iOS 15. Users device is iOS 17.3.1.
0
0
248
Apr ’24
Bitwise operators in predicate with SwiftData
I have a model class with various status values that I would like to store in a single 64 bits integer. For example one bit for this boolean flag, 4 bits for that lookup value and so on. I tried to create a predicate containing bitwise operators to query specific bits but that seems impossible, no way no compile it. is there a way I am no aware of to accomplish this, some workaround or is that planned to be possible in future Swiftdata release? that would be a shame having to store a few status values of 4 or less bits each in different 64bits values, what a waste! Thanks Tof
0
1
216
Apr ’24