Core Data

RSS for tag

Save your application’s permanent data for offline use, cache temporary data, and add undo functionality to your app on a single device using Core Data.

Core Data Documentation

Posts under Core Data tag

360 Posts
Sort by:
Post not yet marked as solved
0 Replies
99 Views
So I know this is probably a stretch, but is there any way to airdrop an object from core data? From what I understand airdrop is only used with links, but is there a way to convert the data of a core data object into a file, convert the file into a link, send it via airdrop, and convert it back into a file, and then add that object from a file to another user's core data storage? Any help would be greatly appreciated. Thanks!!
Posted Last updated
.
Post not yet marked as solved
1 Replies
108 Views
So this project is pretty straightforward. I have an item. The use can create, get a closer look at, delete, or edit an item. For some reason, no matter how many different ways I try to do it, the edit part does not work. I've tried moving the sheet outside of the context menu (it only opens the bottom item), I've tried moving it under the list using the first index of the item (it crashes), and finally I've tried it the shown way and it just doesn't do anything. If anyone can come up with a better way to open the edit view for the correct item (preferably using a context menu, but something similar is acceptable) I would really appreciate it. I've provided the project for a better understanding of what I'm trying to do. If you have any questions just leave a comment. Any help would be greatly appreciated. Content View: struct ContentView: View {     @Environment(\.managedObjectContext) var managedObjContext     @ObservedObject var persistence = PersistenceController.shared     @State private var items = PersistenceController.shared.getItems()     @State private var showingEditView = false     @State private var showingAddView = false          var body: some View {         NavigationView{             List{                 Section(""){                     ForEach(items) { item in                         NavigationLink(destination: ItemView(item: item)){                             Text(item.name!)                         }                         .contextMenu{                             Button(action: {                                 self.showingEditView.toggle()                             }){                                 Text("Edit Item")                             }                             .sheet(isPresented: $showingEditView){                                 EditItemView(item: item)                                     .onDisappear(perform: {                                         items = persistence.getItems()                                     })                             }                         }                     }                     .onDelete(perform: { indexSet in                         deleteItem(indexSet: indexSet)                     })                 }             }             .listStyle(InsetGroupedListStyle())             .cornerRadius(10)             .navigationBarTitle("My Items")             .navigationBarItems(trailing: addButton)             .onAppear(perform: {                 items = persistence.getItems()             })             .sheet(isPresented: $showingAddView){                 AddItemView()                     .onDisappear(perform: {                         items = persistence.getItems()                     })             }         }     }          var addButton: some View {         Button(action: {             showingAddView.toggle()         }){             Text("Add an Item").bold()         }     }          func deleteItem(indexSet: IndexSet){         withAnimation{             indexSet.map {                 items[$0] }                         .forEach(managedObjContext.delete)                          persistence.contextSave()             items = persistence.getItems()         }     } } Item View: struct ItemView: View{     @State var item: Item     var body: some View{         Text(item.name ?? "No Name")     } } Add View: struct AddItemView: View{     @Environment(\.dismiss) var dismiss     @ObservedObject var persistence = PersistenceController.shared     @State private var name = ""     var body: some View {         Form{             TextField("Item Name", text: $name)             Button(action:{                 persistence.addItem(name: name)                 dismiss()             }){                 Text("Add Item")             }         }     } } Edit View: struct EditItemView: View{     @Environment(\.dismiss) var dismiss     @ObservedObject var persistence = PersistenceController.shared     @State var item: Item     @State private var name = ""     var body: some View {         Form{             TextField("Item Name", text: $name)             Button(action:{                 persistence.addItem(name: name)                 dismiss()             }){                 Text("Add Item")             }         }         .onAppear{             name=item.name ?? "No Name"         }     } } Persistence File: class PersistenceController : ObservableObject{     static let shared = PersistenceController()     let container: NSPersistentContainer          init(inMemory: Bool = false) {         container = NSPersistentContainer(name: "Test")         if inMemory {             container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")         }         container.loadPersistentStores(completionHandler: { (storeDescription, error) in             if let error = error as NSError? {                 fatalError("Unresolved error \(error), \(error.userInfo)")             }         })         container.viewContext.automaticallyMergesChangesFromParent = true     }     static var preview: PersistenceController = {         let result = PersistenceController(inMemory: true)         let viewContext = result.container.viewContext         for _ in 0..<10 {             let newItem = Item(context: viewContext)             newItem.id = UUID()             newItem.name = "Test"         }         do {             try viewContext.save()         } catch {             let nsError = error as NSError             fatalError("Unresolved error \(nsError), \(nsError.userInfo)")         }         return result     }()     func getItems() -> [Item] {         let context = container.viewContext         var request = NSFetchRequest<Item>()         request = Item.fetchRequest()         request.entity = NSEntityDescription.entity(forEntityName: "Item", in: context)         do {             let items = try context.fetch(request)             if items.count == 0 { return []}             return items.sorted(by: {$0.name! > $1.name!})         } catch {             print("**** ERROR: items fetch failed \(error)")             return []         }     }          func addItem(name: String){         let context = container.viewContext         let item = Item(context: context)         item.id = UUID()         item.name = name                  contextSave()     }          func contextSave() {         let context = container.viewContext         if context.hasChanges {             do {                 try context.save()                 self.objectWillChange.send()             } catch {                 print("**** ERROR: Unable to save context \(error)")             }         }     } } Data Model:
Posted Last updated
.
Post not yet marked as solved
0 Replies
99 Views
I have an app that relies on Core Data for persistence. The app is using MVVM architecture in order to facilitate testing The dev environment is a MacBook Pro (M1 Max) running MacOS 12.4 and Xcode 14 beta 2 So far everything has been working well until I attempted to add a new entity to my Model that had a relationship (many-to-one) to another entity. Attempting to instantiate one of these entities resulted in a NSUnknownKeyException associated with the property that defined the relationship so I deleted this relationship from the model and re-ran the test. Much to my surprise, the error persisted and I have been singularly unable to resolve it since despite the following: Delete derived data, reboot XCode Rename offending entity (error persists, just with the different entity name) Delete entity and add back into the Model Turn off code-gen and defined the MO subclass manually Check Core Data XML - this looks unremarkable and there are no residual properties that could be causing the problem The one thing I haven't tried yet is to run the code through Xcode 13 (it's a new machine so I was all enthusiastic and went straight for the beta which might have been a mistake!) so will be doing that shortly. For now it seems that something relating to the Core Data model and relationships between entities is hiding out somewhere I can't find it but it could be a bug in the tooling. The problem of course is that I can't continue to develop the app with a compiler error I can't clear. Any thoughts or guidance would be very welcome... Xcode Model interface for relevant entities and XML: Extension on the offending ManagedObject subclass (convenience methods): extension Prescription {     // MARK: - INTERNAL TYPES     enum PointOfCareContext: String, CustomStringConvertible {         case premedication, perioperative, postoperative, hospitalised         var description: String {             return self.rawValue.capitalized         }     }     // MARK: - PROPERTIES     var drug: Drug {         get { guard let drug = cd_drug else {             fatalError("Persistent store corrupted: Prescription is missing relationship to Drug.")         }             return drug         }         set { cd_drug = newValue }     }          var timePrescribed: Date {         get { guard let timePrescribed = cd_timePrescribed else {             fatalError("Persistent store corrupted: Prescription is missing timePrescribed.")         }             return timePrescribed         }         set { cd_timePrescribed = newValue }     }     /// When the drug should be administered     /// Passing nil to this property indicates the drug should be given asap (so will return current Date)     var timeScheduled: Date? {         get { guard let timeScheduled = cd_timeScheduled else {             return Date.now         }             return timeScheduled         }         set { cd_timeScheduled = newValue }     }     /// When the drug was administered     /// Nil indicates not given yet     var timeAdministered: Date? {         get { return cd_timeAdministered }         set { cd_timeScheduled = newValue }     }     var doseRate: Measurement<UnitDensity> {         get {             if (cd_doseRate != 0) {                 fatalError("Persistent store corrupted: Prescription doseRate == 0.")             }             return Measurement(value: cd_doseRate, unit: .milligramsPerKilogram)         }         set {             cd_doseRate = newValue.converted(to: .milligramsPerKilogram).value         }     }     var dose: Measurement<UnitMass> {         get {             return Measurement(value: cd_dose, unit: .milligrams)         }         set {             cd_doseRate = newValue.converted(to: .milligrams).value         }     }     var doseVolume: Measurement<UnitVolume> {         get {             return Measurement(value: cd_doseVolume, unit: .milliliters)         }         set {             cd_doseVolume = newValue.converted(to: .milliliters).value         }     }     var context: PointOfCareContext {         get {             guard let contextValue = cd_context, let context = PointOfCareContext(rawValue: contextValue) else {                 fatalError("Persistent store corrupted: Prescription has an invalid administration context [\(cd_context ?? "")]")             }             return context         }         set {             cd_context = newValue.rawValue         }     } Error encountered when attempting to save managed object context in the unit test:
Posted Last updated
.
Post not yet marked as solved
2 Replies
138 Views
Hi, I recently had an issue with one of my production apps that use Core Data and CloudKit where data wasn't syncing between devices, after a little bit of research I found out that the schema in the private CloudKit container needed to be initialized; which I never did. The part I'm still not 100% sure is when to run the initializeCloudKitSchema method after the app has been released to the AppStore. I see that Apple recommends running it when testing by using #if DEBUG, but... do you really want to run it every time you compile in Xcode? Here is how I understand it at this point... App release, call initializeCloudKitSchema() to match schemas between Core Data and CloudKit. Added or deleted an attribute, call initializeCloudKitSchema() to update the CloudKit schema. Renamed an attribute, call initializeCloudKitSchema() to update the CloudKit schema. Etc. If my assumption above is correct, calling the initializeCloudKitSchema() method during development would update the schema in CloudKit before the new app version is released in the AppStore, therefore creating an issue for existing users with previous versions of the app since they will not have the latest code but will be using the latest schema which contains the new attributes. Can someone please share their method of handling schema updates in CloudKit after the app has been released to the AppStore? Code: do { try container.initializeCloudKitSchema() } catch { print(error) }
Posted
by fsdolphin.
Last updated
.
Post not yet marked as solved
1 Replies
125 Views
I have a SwiftUI app that uses CloudKit and Core data to sync data between devices. Everything works fine when testing on devices in Xcode but not in production in the App Store. Can someone explain the typical process when deploying an app that uses CoreData + CloudKit? Is there anything that needs to be done in code or in the CloudKit Console before the app is uploaded to the App Store? Again, my issue is that data doesn't sync when trying to sync data between multiple devices in production but works fine when testing in Xcode. Thanks
Posted
by fsdolphin.
Last updated
.
Post not yet marked as solved
0 Replies
89 Views
Hi, I have an NSPredicate with format: "ANY containsEntity.id == %lld" I was trying to not-it, but the following don't work: NSCompoundPredicate(notPredicateWithSubpredicate: myPredicate) "NOT(ANY containsEntity.id == %lld)" "NONE containsEntity.id == %lld" containsEntity is a one to many relationship Is this a bug, as the following link may indicate? https://stackoverflow.com/questions/14471910/nspredicate-aggregate-operations-with-none Using the SUBQUERY workaround detailed in that link, adapted to my own query, provided the desired predicate functionality. SUBQUERY(containsEntity, $a, $a.id ==%lld).@count ==0" If it's a bug, that's a surprisingly long lived one, please fix it. Otherwise, I'd be grateful if someone could explain what I'm missing. Thank you in advance, Javier
Posted Last updated
.
Post not yet marked as solved
2 Replies
254 Views
Basically I need a view with a calendar that will show data attributes from the item. I've tried two different approaches both have their listed problems. There must be a better way to do something like this. Surely it's not ideal to create a new item every time a date is opened or constantly check if something is there, but I don't know any other way. Actual View: import SwiftUI import CoreData struct ContentView: View {     @Environment(\.managedObjectContext) var managedObjContext     @Environment(\.calendar) var calenda     @Environment(\.dismiss) var dismiss     @FetchRequest(sortDescriptors: [], predicate: NSPredicate(format: "timestamp == %@", Date.now as CVarArg)) var items: FetchedResults<Item>          @State private var date = Date.now          var body: some View {         NavigationView{             VStack{                 DatePicker("Calendar", selection: $date, in: Date.now...,displayedComponents: [.date])                     .datePickerStyle(.graphical)                     .onAppear(perform: {                         if (items.isEmpty){                             PersistenceController().addItem(date: date, context: managedObjContext)                         }                     })                     .onChange(of: date){ value in                         items.nsPredicate=NSPredicate(format: "timestamp == %@", date as CVarArg)                         if (items.isEmpty){                             PersistenceController().addItem(date: date, context: managedObjContext)                         }                     }                 if (!items.isEmpty){ //This is the only difference in the two approaches. I just put either one of the next two blocks of code in here                 }             }             .navigationBarTitle("My Planner")         }     }          func getTitle(date: Date)->String{         let formatter = DateFormatter()         formatter.dateStyle = .medium         return formatter.string(from: date)     } } First (looks correct, but doesn't show the changes live): PlannedMealsView(item: items[0]) Spacer() //And then this is added at the bottom struct PlannedMealsView: View {     @Environment(\.managedObjectContext) var managedObjContext     @State var item: Item     var body: some View {             VStack{                 Text(item.timestamp ?? Date.now, style: .date)                     .font(.title2)                     .bold()                 Section("Word"){                     if(item.word != nil){                         HStack{                             Spacer()                             Text(item.word!)                             Spacer()                             Button(action: {                                 PersistenceController().removeFromItem(item: item, context: managedObjContext)                             }){                                 Image(systemName: "minus.circle").bold()                             }                             Spacer()                         }                     } else {                         Button(action: {                             PersistenceController().addToItem(item: item, context: managedObjContext)                         }){                             Image(systemName: "plus.circle").bold()                                 .padding(.vertical, 10)                                 .padding(.horizontal, 20)                         }                     }                 }                 Spacer()             }             .frame(height:200)     } } Second (allows direct access to the objects data, but bugs after 5 or 6 date changes): VStack{                             Text(items[0].timestamp ?? Date.now, style: .date)                                 .font(.title2)                                 .bold()                             Section("Word"){                                 if(items[0].word != nil){                                     HStack{                                         Spacer()                                         Text(items[0].word!)                                         Spacer()                                         Button(action: {                                             PersistenceController().removeFromItem(item: items[0], context: managedObjContext)                                         }){                                             Image(systemName: "minus.circle").bold()                                         }                                         Spacer()                                     }                                 } else {                                     Button(action: {                                         PersistenceController().addToItem(item: items[0], context: managedObjContext)                                     }){                                         Image(systemName: "plus.circle").bold()                                             .padding(.vertical, 10)                                             .padding(.horizontal, 20)                                     }                                 }                             }                         Spacer()                     }                     .frame(height:200) Unchanged Files: Persistence- import CoreData struct PersistenceController {     static let shared = PersistenceController()     let container: NSPersistentContainer     init(inMemory: Bool = false) {         container = NSPersistentContainer(name: "Test")         if inMemory {             container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")         }         container.loadPersistentStores(completionHandler: { (storeDescription, error) in             if let error = error as NSError? {                 fatalError("Unresolved error \(error), \(error.userInfo)")             }         })         container.viewContext.automaticallyMergesChangesFromParent = true     }          func addItem(date: Date, context: NSManagedObjectContext){         let item = Item(context: context)         item.timestamp = date         item.word = nil                  save(context: context)     }          func addToItem(item: Item, context: NSManagedObjectContext){         item.word = "Test"                  save(context: context)     }          func removeFromItem(item: Item, context: NSManagedObjectContext){         item.word = nil                  save(context: context)     }          func save(context: NSManagedObjectContext){         do {             try context.save()         } catch {             let nsError = error as NSError             fatalError("Unresolved error \(nsError), \(nsError.userInfo)")         }     } } Data Model- If you have any questions I'll be happy to answer. Any help is greatly appreciated. All the best!
Posted Last updated
.
Post not yet marked as solved
6 Replies
255 Views
Hi. I want to make a planner app that has the date and location of the project. Only I have a problem. I used a "DatePicker" so that the date is counted. Only I do not know how to save and display the selected date. In general I have problems to save and reload the content of the variables and texfielders etc. I thought that these contents are automatically saved on the end device of the user. I have read that there are methods like "UserDefaults", "CoreData" or "AppStorage". Have been reading stuff about this forever. But I can't get this to work. I hope someone would like to donate their time to help. Greetings Janik
Posted Last updated
.
Post not yet marked as solved
0 Replies
105 Views
Does anyone know the best way to store core data using a calendar? The only way I could think is adding a date attribute and every time the date is changed on the calendar changing the NSPredicate to that date and if there isn’t one creating a new instance with that date as it’s date value. I’m certain this is not the best method, but I couldn’t think of any other, but I know I’m very limited in my SwiftUI knowledge. So any guidance would be greatly appreciated. For more insight into what I’m looking for see my previous post asking for advice on what to change about my own method: https://developer.apple.com/forums/thread/708915
Posted Last updated
.
Post not yet marked as solved
6 Replies
1.8k Views
Recently I update my App a new version in App Store . What I do is only add a new Entity and add one new column to an existing Entity.Then over than 200 users run into crash when they update(Not all users run into this). This is how I create Core Data Stack. class AppGroupLocalPersistentContainer: NSPersistentContainer { &#9;&#9;open override class func defaultDirectoryURL() -> URL { &#9;&#9;&#9;&#9;let storeURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.mindo") &#9;&#9;&#9;&#9;return storeURL! &#9;&#9;} } extension NSPersistentContainer { &#9;&#9;var url: URL? { &#9;&#9;&#9;&#9;let url: URL? = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.mindo") &#9;&#9;&#9;&#9;return url?.appendingPathComponent("Mindo.sqlite") &#9;&#9;} } public class LocalCoreData { &#9;&#9;deinit { &#9;&#9;&#9;&#9;Logger.info("LocalCoreData deinit") &#9;&#9;} &#9;&#9;lazy var localContext: NSManagedObjectContext = { &#9;&#9;&#9;&#9;let context = localContainer.viewContext &#9;&#9;&#9;&#9;context.mergePolicy = NSMergePolicy(merge: NSMergePolicyType.mergeByPropertyObjectTrumpMergePolicyType) &#9;&#9;&#9;&#9;context.automaticallyMergesChangesFromParent = true &#9;&#9;&#9;&#9;context.stalenessInterval = 0 &#9;&#9;&#9;&#9;return context &#9;&#9;}() &#9;&#9;lazy var localContainer: NSPersistentContainer = { &#9;&#9;&#9;&#9;let container = AppGroupLocalPersistentContainer(name: "Mindo", managedObjectModel: NSManagedObjectModel.mergedModel(from: [Bundle.main])!) &#9;&#9;&#9;&#9;guard let description = container.persistentStoreDescriptions.first else { &#9;&#9;&#9;&#9;&#9;&#9;fatalError("Failed to retrieve a persistent store description.") &#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) &#9;&#9;&#9;&#9;description.setOption(false as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) &#9;&#9;&#9;&#9;description.shouldMigrateStoreAutomatically = true &#9;&#9;&#9;&#9;description.shouldInferMappingModelAutomatically = true &#9;&#9;&#9;&#9; &#9;&#9;&#9;&#9;container.loadPersistentStores(completionHandler: { _, error in &#9;&#9;&#9;&#9;&#9;&#9;if let error = error as NSError? { &#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;fatalError("Unresolved error \(error), \(error.userInfo)") &#9;&#9;&#9;&#9;&#9;&#9;} &#9;&#9;&#9;&#9;}) &#9;&#9;&#9;&#9;return container &#9;&#9;}() } And here is part of crash log I copy from Xcode Organizer. Thread 0 name: Thread 0 Crashed: 0&#9; libswiftCore.dylib&#9;&#9;&#9;&#9;&#9;&#9; 0x0000000187d45cb4 _assertionFailure(_:_:file:line:flags:) + 492 (AssertCommon.swift:132) 1&#9; libswiftCore.dylib&#9;&#9;&#9;&#9;&#9;&#9; 0x0000000187d45cb4 _assertionFailure(_:_:file:line:flags:) + 492 (AssertCommon.swift:132) 2&#9; Mindo&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; 0x0000000104245088 closure #1 in closure #1 in LocalCoreData.localContainer.getter + 604 (LocalCoreData.swift:39) 3&#9; Mindo&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; 0x00000001042449a0 thunk for @escaping @callee_guaranteed (@guaranteed NSPersistentStoreDescription, @guaranteed Error?) -> () + 64 (<compiler-generated>:0) 4&#9; CoreData&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; 0x000000018a3da570 -[NSPersistentStoreCoordinator _doAddPersistentStoreWithDescription:privateCopy:completeOnMainThread:withHandler:] + 1008 (NSPersistentStoreCoordinator.m:1461) 5&#9; CoreData&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; 0x000000018a28146c -[NSPersistentStoreCoordinator addPersistentStoreWithDescription:completionHandler:] + 268 (NSPersistentStoreCoordinator.m:1507) 6&#9; CoreData&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; 0x000000018a4ae880 -[NSPersistentContainer _loadStoreDescriptions:withCompletionHandler:] + 232 (NSPersistentContainer.m:284) 7&#9; CoreData&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; 0x000000018a289658 -[NSPersistentContainer loadPersistentStoresWithCompletionHandler:] + 316 (NSPersistentContainer.m:271) 8&#9; Mindo&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9; 0x0000000104244d10 closure #1 in LocalCoreData.localContainer.getter + 848 (LocalCoreData.swift:36) I know the error is occur in this line :LocalCoreData.swift:39 fatalError("Unresolved error \(error), \(error.userInfo)") But I have no idea how to fix this.
Posted
by yueyuemax.
Last updated
.
Post not yet marked as solved
2 Replies
163 Views
Anyone know how to load a large number of records into the CloudKit public database? I need to load 1.2million records (about 150Mb) into the public database. no binary data. basically just a bunch of exchange rates that I need to have available to all my users. I've been trying for months. have tried: loading into core data on a device or simulator individually or in batches ranging from 400 records to 2500 (more than that exceeds batch size limits). it will start to sync and then stop. can often get it to restart by restarting device or similator but will eventually corrupt the database in iCloud requiring a reset of the environment. generally can get the load to go for a few days and load maybe 500k records before it breaks. to do that have to put delays up to a minute between batches loaded into core data. have tried doing it using the CloudKit.js framework and loading from a server. this works for a small number of records. but limits are really small doing it through that interface. after a while it locks you out. don't get anywhere near the number of records I need to load. I'm stuck. has anyone found a way? same issue on all versions of iOS - 14, 15, 16b1
Posted
by ngb.
Last updated
.
Post not yet marked as solved
0 Replies
93 Views
There was a section in the talk about how we can break down migration into smaller changes, and that we have an opportunity to run app-specific code in between migration steps. However the talk didn't touch on how can can achieve this, besides a single sentence, which doesn't give enough detail at least for me to figure out how to do it. Intuitively, an event loop could be built that opens the persistent store with the lightweight migration options set and iteratively steps through each unprocessed model in a serial order, and Core Data will migrate the store. Given the automatic nature of the lightweight migrations, especially in the case where we're using NSPersistentCoordinator, doesn't the automatic system just zoom through all of the migrations from model A --> A' --> A'' -> B? How to we make it stop so we can execute our own app code? Thanks!
Posted
by json.
Last updated
.
Post not yet marked as solved
0 Replies
94 Views
Hi, any side effect to be aware of when changing a core data relationship delete rule from Null to Cascade? I NSPersistentCloudKitContainer to handle CloudKit sync in case that's relevant. It doesn't look like any migration is required, and the cloudkit schema doesn't change so it seems there's nothing to do on the cloudkit-side either. However I'd prefer to double check to avoid making false assumptions. I wasn't able to find any documentation on that particular point so if someone can shade some light on how things work under the hood that would be appreciated. Thanks!
Posted
by 0o0.
Last updated
.
Post not yet marked as solved
1 Replies
173 Views
I am trying to add CloudKit sharing to my app using the new iOS 15 share method  https://developer.apple.com/documentation/coredata/nspersistentcloudkitcontainer/3746834-sharemanagedobjects In the app there are 3 core data entities (Folder, Item, Comment) with the following relationships: A Folder contains many Items An Item has many Comments I want to use CloudKit to share just the Item entity, not any of its relationships. Is this possible to do with the share(_:to:completion:) method? Currently, when I pass an Item to the share method it also includes the Folder and Comments in the CKShare. How do I prevent this? A similar question was posted here with no response: https://developer.apple.com/forums/thread/697630
Posted
by ethan5513.
Last updated
.
Post marked as solved
19 Replies
5.2k Views
Background I have an established app in the App Store which has been using NSPersistentCloudkitContainer since iOS 13 without any issues. I've been running my app normally on an iOS device running the iOS 15 betas, mainly to see problems arise before my users see them. Ever since iOS 15 (beta 4) my app has failed to sync changes - no matter how small the change. An upload 'starts' but never completes. After a minute or so the app quits to the Home Screen and no useful information can be gleaned from crash reports. Until now I've had no idea what's going on. Possible Bug in the API? I've managed to replicate this behaviour on the simulator and on another device when building my app with Xcode 13 (beta 5) on iOS 15 (beta 5). It appears that NSPersistentCloudkitContainer has a memory leak and keeps ramping up the RAM consumption (and CPU at 100%) until the operating system kills the app. No code of mine is running. I'm not really an expert on these things and I tried to use Instruments to see if that would show me anything. It appears to be related to NSCloudkitMirroringDelegate getting 'stuck' somehow but I have no idea what to do with this information. My Core Data database is not tiny, but not massive by any means and NSPersistentCloudkitContainer has had no problems syncing to iCloud prior to iOS 15 (beta 4). If I restore my App Data (from an external backup file - 700MB with lots of many-many, many-one relationships, ckAssets, etc.) the data all gets added to Core Data without an issue at all. The console log (see below) then shows that a sync is created, scheduled & then started... but no data is uploaded. At this point the memory consumption starts and all I see is 'backgroundTask' warnings appear (only related to CloudKit) with no code of mine running. CoreData: CloudKit: CoreData+CloudKit: -[PFCloudKitExporter analyzeHistoryInStore:withManagedObjectContext:error:](501): <PFCloudKitExporter: 0x600000301450>: Exporting changes since (0): <NSPersistentHistoryToken - { "4B90A437-3D96-4AC9-A27A-E0F633CE5D9D" = 906; }> CoreData: CloudKit: CoreData+CloudKit: -[PFCloudKitExportContext processAnalyzedHistoryInStore:inManagedObjectContext:error:]_block_invoke_3(251): Finished processing analyzed history with 29501 metadata objects to create, 0 deleted rows without metadata. CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _scheduleAutomatedExportWithLabel:activity:completionHandler:](2800): <NSCloudKitMirroringDelegate: 0x6000015515c0> - Beginning automated export - ExportActivity: <CKSchedulerActivity: 0x60000032c500; containerID=<CKContainerID: 0x600002ed3240; containerIdentifier=iCloud.com.nitramluap.Somnus, containerEnvironment="Sandbox">, identifier=com.apple.coredata.cloudkit.activity.export.4B90A437-3D96-4AC9-A27A-E0F633CE5D9D, priority=2, xpcActivityCriteriaOverrides={ Priority=Utility }> CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate executeMirroringRequest:error:](765): <NSCloudKitMirroringDelegate: 0x6000015515c0>: Asked to execute request: <NSCloudKitMirroringExportRequest: 0x600002ed2a30> CBE1852D-7793-46B6-8314-A681D2038B38 2021-08-13 08:41:01.518422+1000 Somnus[11058:671570] [BackgroundTask] Background Task 68 ("CoreData: CloudKit Export"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(_:) for your task in a timely manner to avoid this. 2021-08-13 08:41:03.519455+1000 Somnus[11058:671570] [BackgroundTask] Background Task 154 ("CoreData: CloudKit Scheduling"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(_:) for your task in a timely manner to avoid this. Just wondering if anyone else is having a similar issue? It never had a problem syncing an initial database restore prior to iOS 15 (beta 4) and the problems started right after installing iOS 15 (beta 4). I've submitted this to Apple Feedback and am awaiting a response (FB9412346). If this is unfixable I'm in real trouble (and my users are going to be livid). Thanks in advance!
Posted Last updated
.
Post marked as solved
1 Replies
178 Views
I'm working on hooking up a Multiplatform app with CloudKit (using CoreData) and I was wondering if anyone knows any current tutorials to help me understand the process better? I was trying to wrap my head around the WWDC 2022 tutorial CoreDataCloudKitDemo but it isn't SwiftUI and I'm getting bogged down by the non-relevant code. Thanks everyone :)
Posted Last updated
.
Post marked as solved
2 Replies
242 Views
So I've found a way to convert fetched results to an array of the same data type, and not only that but filter them with the fetch request given a string: func searchResults(searchingFor: String)->[Recipe]{     var filteredRecipeList=[Recipe]()     @FetchRequest(sortDescriptors: [SortDescriptor(\.date, order: .reverse)], predicate: NSPredicate(format: "title CONTAINS[c] %@",searchingFor)) var filteredResults: FetchedResults<Recipe>     for recipe in filteredResults {         filteredRecipeList.append(recipe)     }     return filteredRecipeList } To clarify, this would ideally return an array with a list of Recipes that contain the given string in the title. In theory this should work just fine, but I'm getting a weird error. I've never seen an error like this and I'm not sure how to understand it. It is purple with a yellow warning. The error says "Accessing StateObject's object without being installed on a View. This will create a new instance each time." How do I get around this issue to accomplish what I'm trying to accomplish. Thanks in advance for any help whatsoever. I'll upvote anyone with any bit of helpful information. Have a good one!
Posted Last updated
.
Post marked as solved
4 Replies
235 Views
So I was making a relationship between two entities in my data model and got a good ways in when I tried to run it and got a bunch of weird errors. Did I do something wrong to make this happen and if so what do I need to do? I've troubleshooted enough to realize that it happens as soon as I create a new entity. These are the errors.
Posted Last updated
.
Post marked as solved
1 Replies
167 Views
I had the idea of adding a list feature in my app where users can create a list and add multiple recipes to the app so first and only thing I did was add an entity to my data model called "List" that contains a string: title and an array of Recipes: recipes (I remembered to put "NSSecureUnarchiveFromData" in Transformer and put [Recipe] for custom class). Afterwards I made the relationship in both entities and made them inverse. I made no other changes to my code. But I ran it just to make sure nothing went wrong and lo and behold: 7 never before seen errors, but only in one file. Before adding this entity this same code compiled just fine. This is the file and these are the errors I'm getting. Any help would be greatly appreciated. import SwiftUI struct RecipeView: View {     @Environment (\.managedObjectContext) var managedObjContext     @Environment(\.dismiss) var dismiss          var recipe: FetchedResults<Recipe>.Element     @State var isFavorite: Bool     @State var servings = -1          var body: some View {         VStack(alignment: .leading){ //Error: Trailing closure passed to parameter of type 'CGFloat?' that does not accept a closure             if (recipe.notes! != ""){                 Section{                     Text(recipe.notes!)                         .font(.headline)                 }                 .padding(.horizontal)             }             HStack{                 Spacer()                 Text("Total Time: "+calcTime(time:Int(recipe.totalTime!) ?? 0))                 Spacer()                 Text("Servings: "+recipe.servings!)                 Spacer()             }             .padding(.vertical)             Grid{                 GridRow{                     Button {                         isFavorite.toggle()                         recipe.isFavorite.toggle()                         PersistenceController().save(context: managedObjContext)                     } label: {                         HStack{                             Image(systemName: isFavorite ? "star.fill" : "star")                                 .foregroundStyle(.yellow)                             Text(isFavorite ? "Unfavorite" : "Favorite")                                 .foregroundColor(Color(UIColor.lightGray))                         }                         .frame(width: 300,height: 50)                         .background(Color(UIColor(hexString: "#202020")))                         .border(Color(UIColor(hexString: "#202020")))                         .cornerRadius(5)                     }                     Button {                         print("implement list functionality")                     } label: {                         Image(systemName: "plus")                             .frame(width: 50,height: 50)                             .background(Color(UIColor(hexString: "#202020")))                             .border(Color(UIColor(hexString: "#202020")))                             .cornerRadius(5)                     }                 }             }             .padding(.horizontal)             List{                 NavigationLink(destination: ingredientsView(ingredients: recipe.ingredients!)){                     HStack{                         Text("List of Ingredients")                         Spacer()                         Text(String(recipe.ingredients!.count))                             .foregroundColor(.gray)                     }                 }                 .frame(height: 50)                 NavigationLink(destination: instructionsView(instructions: recipe.instructions!)){                     HStack{                         Text("List of Instructions")                         Spacer()                         Text(String(recipe.instructions!.count))                             .foregroundColor(.gray)                     }                 }                 .frame(height: 50)             }             .listStyle(.grouped)             .scrollDisabled(true)             Spacer()         }         .navigationBarTitle(recipe.title!)         .navigationBarItems(trailing: shareButton)         .onAppear{             PersistenceController().updateDate(recipe: recipe, context: managedObjContext)         }         Spacer()     }     var shareButton: some View{         Button(action: {             print("Implement airdrop feature")         }){             Image(systemName: "square.and.arrow.up")                 .foregroundStyle(.blue)         }     } } struct ingredientsView: View{     @State var ingredients: [String]     var body: some View{         List{ // Error: Trailing closure passed to parameter of type 'NSManagedObjectContext' that does not accept a closure             Section(""){                 ForEach(ingredients,id: \.self){ String in                     NavigationLink(destination:                                     NavigationView{                         Text(String)                             .frame(alignment:.center)                             .font(.title)                     }){                         Text(String).lineLimit(1)                     }                 }             }         }         .frame(alignment: .center) //Error: Cannot infer contextual base in reference to member 'center' //Error: Value of type 'List' has no member 'frame'         .cornerRadius(10)         .navigationTitle("Ingredients List")     } } struct instructionsView: View{     @State var instructions: [String]     var body: some View{         List{ // Error: Trailing closure passed to parameter of type 'NSManagedObjectContext' that does not accept a closure             Section(""){                 ForEach(instructions,id: \.self){ String in                     NavigationLink(destination:                                     NavigationView{                         Text(String)                             .frame(alignment:.center)                             .font(.title)                     }){                         Text(String).lineLimit(1)                     }                 }             }         }         .frame(alignment: .center) //Error: Cannot infer contextual base in reference to member 'center' //Error: Value of type 'List' has no member 'frame'         .cornerRadius(10)         .navigationTitle("Instructions List")     } }
Posted Last updated
.