Build apps that share data through CloudKit and Core Data

RSS for tag

Discuss the WWDC21 session Build apps that share data through CloudKit and Core Data.

Posts under wwdc21-10015 tag

34 Posts

Post

Replies

Boosts

Views

Activity

How is Record Zone Sharing done?
My use case is the following: Every user of my app can create as an owner a set of items.  These items are private until the owner invites other users to share all of them as participant. The participants can modify the shared items and/or add other items. So, sharing is not done related to individual items, but to all items of an owner. I want to use CoreData & CloudKit to have local copies of private and shared items. To my understanding, CoreData & CloudKit puts all mirrored items in a special zone „com.apple.coredata.cloudkit.zone“. So, this zone should be shared, i.e. all items in it. In the video it is said that NSPersistentCloudKitContainer uses Record Zone Sharing optionally in contrast to hierarchically record sharing using a root record. But how is this done? Maybe I can declare zone „com.apple.coredata.cloudkit.zone“ as a shared zone?
2
0
1.2k
Apr ’25
Thread 1: "-[entity_name relation_name]: unrecognized selector sent to instance 0x600003812bc0"
I'm finding this issue after making sure I create an entity with the correspondent attribute. This issue comes from a relation between 2 entities: GroupData and TopicData. Their relations are like shown in the screenshots. Then, I get the context from a function like the next one. Every time I need to use the context, I call this function. import CoreData class DataController: ObservableObject {     let container = NSPersistentContainer(name: "vocabul-R")     init() {         container.loadPersistentStores { description, error in                 if let error = error {                     print("CoreData failed to load: \(error.localizedDescription)")                 }         }         container.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump         container.viewContext.retainsRegisteredObjects = true     } } I first create the objects from data I get from csv files. By debugging I've made sure that the objects created have the correspondent values for each attribute and the correct objects in relations.     guard let filepath = Bundle.main.path(forResource: data_file, ofType: "csv") else {         return     }     let dataController = DataController()     let context = dataController.container.viewContext     do {         try context.save()         }     catch {     }     var data = ""     do {         data = try String(contentsOfFile: filepath)     } catch {         return     }     var rows = data.components(separatedBy: "\n")     rows.remove(at: 0)     for row in rows {         let columns = row.components(separatedBy: ",")         let name = columns[0]         let activation_level = (columns[1] as NSString).integerValue         let activated: Bool = false         let last_opened_group: Int16 = 0         let current_level: Int16 = 0         let topic = TopicData(context: context)         topic.name = name         topic.activated = activated         topic.activationLevel = Int16(activation_level)         topic.last_opened_group = last_opened_group         topic.current_level = current_level         do {             try context.save()             }         catch {             print("Context not saved")         }     } } func parseCSV_groups (data_file: String, topic_name: String) {     guard let filepath = Bundle.main.path(forResource: data_file, ofType: "csv") else {         return     }     var data = ""     do {         data = try String(contentsOfFile: filepath)     } catch {         return     }     var rows = data.components(separatedBy: "\n")     rows.remove(at: 0)     let dataController = DataController()     let context = dataController.container.viewContext     let topic = TopicData.getTopicFromName(name: topic_name, context: context)     let train_list = Train_list(context: context)     let test_list = Test_list(context: context)     train_list.train_list = "train_list"     test_list.test_list = "test_list"     for row in rows {         let columns = row.components(separatedBy: ",")         let index_group = (columns[0] as NSString).integerValue         let mean_level = (columns[1] as NSString).integerValue         let cleared_words: Int16 = 0         let group = GroupData(context: context)         group.index_group = Int16(index_group)         group.mean_level = Int16(mean_level)         group.cleared_words = cleared_words         //group.topic = topic         topic.addToGroup(group)         do {             try context.save()             }         catch {             print("Context not saved")         }     } } I have created objects from both entities with relations. I have other functions with relations between these and other entities seem to work fine. But now I need to get all the groups that one TopicData object has. For that, I first get a topic from its name.         let fetchRequest = NSFetchRequest<TopicData>(entityName: "TopicData")         fetchRequest.predicate = NSPredicate(format: "name = %@", name)         let topics = (try? context.fetch(fetchRequest)) ?? []         let topic = topics.first ?? TopicData()         return topic     } This seems to work fine as I can print the topic name and the object type (which is TopicData). But then I try to get the groups that it has. I've also tried to get the groups with a fetchRequest     /fetchRequest.predicate = NSPredicate(format: "topic = %@", topic)     let groups = (try? context.fetch(fetchRequest)) ?? [] And when I try to get one of the attributes (activated) of one of these topics, I also get an error. I thought this could be happening because every time I use a topic to update it and save it on context again, a new topic is created which may not be related to GroupData. But I added a constraint in TopicData for name and I still get the same error. Another thing I thought is that relations could be disappearing, since I saw some people had this problem and the issue was that. But I added the retainsRegisteredObjects line in DataController and it didn't work. The full error I get is: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TopicData group]: unrecognized selector sent to instance 0x600003812bc0' terminating with uncaught exception of type NSException I think that is all about the problem. Any idea of what could be happening? I think I added everything relevant for the problem, but let me know if there is some other code I should add. Thank you!
3
0
1.3k
May ’22
Error: Unrecognised selector sent to instance
I'm getting this error because it seems the database forgets objects relations. I always use the same context (with different instances on each function), so I think I can't do anything with mutableSetValue. Also, I've tried to set retainsRegisteredObjects, but it doesn't seem to improve anything. An option I was thinking about is always using the same context and send it from one function to the next one, but it doesn't feel like that's an optimal solution. And I'm not sure if relations would stay after I closed the app, which is something I need. Any ideas of how to solve this issue?
3
0
684
May ’22
NSPersistantCloudkitContainer record modification outside of UICloudSharingController
I’m new to trying to modify share records and not having any luck with it. Somehow, I’ve made it such that every new coredata record I create is already listed as shared and accepted by another user (my other sandbox). This user never got a link nor has the record. I’d like to correct that issue. But hacking away at it, I can’t find a solution or even know what caused this. I assume I need to modify the record of the privateCloudDatabase?
0
0
1.1k
May ’22
NSPersistentCloudKitContainer Bug
I have been excited to add NSPersistentCloudKitContainer's share functionality to my app but I've noted a few thing I suspect are bugs: -When using share() on a NSManagedObject the share record is set up in a new zone. However, the root NSManagedObject's record is not being updated with the relationship linkage to the shared record. -Secondly, when you revoke a share, the cloudkit.share record is removed from iCloud, but not in the local data stores. This makes the fetchShares() method ineffective for detecting a missing cloudkit.share record. In order to re-share the root object the developer must call out to iCloud directly using the old methods to be sure if the share exists or not. I am using the code from Apple's 'Synchronizing a Local Store to the Cloud' sample. It would be nice if they added support for revoking shares into this sample and addressed these issues.
8
0
6.1k
Apr ’22
Deleting a Share without deleting Objects
Hi, I wanted to offer the UI for editing and deleting a share. So for using UICloudSharingController(share: , container: ) I implemented the delegate to call "persistUpdatedShare" in "cloudSharingControllerDidSaveShare" func cloudSharingControllerDidSaveShare(_ csc: UICloudSharingController) { if let share = csc.share,   let privatePersistentStore = PersistenceController.shared.privatePersistentStore { PersistenceController.shared.container.persistUpdatedShare(share, in: privatePersistentStore) { (share, error) in Thread.performOnMain { if let error = error { PersistenceController.shared.storeWarning = error } } } } } and to call "purgeObjectsAndRecordsInZone" in "cloudSharingControllerDidStopSharing" func cloudSharingControllerDidStopSharing(_ csc: UICloudSharingController) { let puzzleToShare = puzzleToShare if let share = csc.share,   let privatePersistentStore = PersistenceController.shared.privatePersistentStore { PersistenceController.shared.container.purgeObjectsAndRecordsInZone(with: share.recordID.zoneID, in: privatePersistentStore) { (zoneID, error) in Thread.performOnMain { if let error = error { PersistenceController.shared.storeWarning = error } else { puzzleToShare.makePrivateDuplicate() try? puzzleToShare.puzzle.managedObjectContext?.save() } } } } } I got this implementation from a TSI, but it makes no sense to me to delete and duplicate my objects rather than just keeping them and only deleting the share. Question: How can I cleanly discontinue a share, but keep my data. Duplicating my objects seems such a weird approach. But without this implementation it does not really work. (I get strange behaviors and crashes) All the best Christoph
1
0
1.2k
Mar ’22
CloudKit - Problems with template application
G'day everyone, I've had some problems with CoreData+CloudKit, and figured I would go back to basics and start from scratch with a new project. (Note: I'm using the Xcode 13.0 Beta with iOS 15 to try to use sharing on NSPersistentCloudKitContainer as discussed in WWDC2021, but these problems are scattered over the net without any answers to date) When I go through the motions of adding iCloud to the project, assign a new (unique) container and then build the app, two problems arise: the simulator comes back with a blank screen (without the Edit or add controls from the boilerplate). Even the preview pane seems broken (no "Add Item" button). This worked in Xcode 12, so I am assuming there is something that's come up as a bug here. More importantly, I get a swath of errors and warnings in the debug console related to CloudKit. It looks like there is some sort of identity problem here. There is no schema generated as yet in the CloudKit dashboard, so I am guessing that the migration errors are happening because the database hasn't yet established because of the identify problem. Does anyone have any insight into what I'm missing here? Thanks.
7
0
2.6k
Mar ’22
How to properly "Delete a row from a tableView" using trailingSwipeActionsConfiguration
I have been stuck on this for some time now, I built a tableView App with the ability to delete a row. I am using with CoreData and iCloud. When I use "editActionsForRowAt" it deletes from the view and does not re-appear when I close and run the App again, the problem is as you know it is deprecated in iOS 13. 1.) This works great but is deprecated in iOS 13 override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? { //Social Sharing Button let shareAction = UITableViewRowAction(style: UITableViewRowAction.Style.default, title: "share", handler: { (action, indexPath) -> Void in _ = "Just checking in at " + self.inspections[indexPath.row].stateID! }) // Delete Button let deleteAction = UITableViewRowAction(style: UITableViewRowAction.Style.default, title: "Delete",handler: { (action, indexPath) -> Void in if let appDelegate = (UIApplication.shared.delegate as? AppDelegate) { let context = appDelegate.persistentContainer.viewContext let inspectionsToDelete = self.fetchResultController.object(at: indexPath) context.delete(inspectionsToDelete) appDelegate.saveContext() } }) deleteAction.backgroundColor = UIColor(red: 237.0/255.0, green: 66.0/255.0, blue: 106.0/255.0, alpha: 1.0) shareAction.backgroundColor = UIColor(red: 63.0/255.0, green: 212.0/255.0, blue: 78.0/255.0, alpha: 1.0) return [deleteAction, shareAction] } 2.) So I ran with "trailingSwipeActionsConfigurationForRowAt" This should work but it will not swipe to delete the row. func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationsForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let deleteAction = UIContextualAction(style: .normal, title: "Delete", handler: {(action, view, success) in if let appDelegate = (UIApplication.shared.delegate as? AppDelegate) { let context = appDelegate.persistentContainer.viewContext let inspectionsToDelete = self.fetchResultController.object(at: indexPath) context.delete(inspectionsToDelete) appDelegate.saveContext() } }) return UISwipeActionsConfiguration(actions: [deleteAction]) } 3.) This deletes without 1.) or 2.) but repopulates the row when I reopen the App override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { // delete the row from the data source inspections.remove(at: indexPath.row) } tableView.deleteRows(at: [indexPath], with: .fade) }
2
0
1.5k
Mar ’22
Unable to handle conflict reported by NSCloudKitMirroringDelegate
I'm working on an app that uses NSPersistentCloudKitContainer to handle CloudKit sharing. Against all odds I've gotten the sharing to work, but now I'm seeing errors on startup that look very much like some kind of background loop trying to merge changes from multiple users and failing. In a more traditional CloudKit installation not backed on NSPersistentCloudKitContainer this feels like a case where I'd have to provide some code to handle the merge. In the brave new world I can't seem to find anyway to affect this Mirroring Delegate. It starts when I initialize the NSPersistentCloudKitContainer and produces the error below (as well as a long stream of similar errors). Any ideas? error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _exportFinishedWithResult:exporter:](1347): <PFCloudKitExporter: 0x282d2ead0>: Export failed with error: <CKError 0x280079470: "Partial Failure" (2/1011); "Failed to modify some records"; partial errors: { cloudkit.zoneshare:(Pacts:__defaultOwner__) = <CKError 0x280079680: "Server Record Changed" (14/1022); "Participants conflict while trying to update share from the server. Participants: === Client: (     "<CKShareParticipant: 0x100cebb70; participantID=..., isCurrentUser=true, role=owner, permission=readWrite, acceptanceStatus=Accepted, identity=<CKUserIdentity: 0x100c4cae0; userID=__defaultOwner__:(_defaultZone:__defaultOwner__), nameComponents=, cached=false, publicKeyVersion=2>, hasProtectionInfo=true, invitationTokenStatus=Healthy, isAnonymousInvitedParticipant=false>" ) === Server: (     "<CKShareParticipant: 0x100c26db0; participantID=..., isCurrentUser=true, role=owner, permission=readWrite, acceptanceStatus=Accepted, identity=<CKUserIdentity: 0x100c13b60; userID=__defaultOwner__:(_defaultZone:__defaultOwner__), nameComponents=..., lookupInfo=<CKUserIdentityLookupInfo: 0x100c13c00; email=...>, cached=false, publicKeyVersion=2>, hasProtectionInfo=true, invitationTokenStatus=Healthy, isAnonymousInvitedParticipant=false>",     "<CKShareParticipant: 0x100c25960; participantID=..., isCurrentUser=false, role=user, permission=readWrite, acceptanceStatus=Accepted, identity=<CKUserIdentity: 0x100c259f0; userID=_6cd4c7c8091c946d4b8e704efbfc0bc4:(_defaultZone:__defaultOwner__), nameComponents=..., lookupInfo=<CKUserIdentityLookupInfo: 0x100c68d10; email=...>, cached=false, publicKeyVersion=2>, hasProtectionInfo=true, invitationTokenStatus=Healthy, isAnonymousInvitedParticipant=false>" )"> }>
1
0
1.1k
Mar ’22
automatic update for @FetchedResults
Hi, I always though @FetchedResults should automatically update, but it seems this is not always true, or do I have to trigger updates myself? I am using Core Data with CloudKit sync. When I start my app, nothing is visually updating while it'S doing the first sync. Only after that view is reloaded it shows the synced data. Any idea what I have to do automatically get updates when the data is syncing the background. All the best Christoph
1
0
1.2k
Mar ’22
Error start simulator Xcode
Hi, I'm building and when it start the app install in the simulator, this error happens Domain: NSPOSIXErrorDomain Code: 53 Failure Reason: Software caused connection abort -- System Information macOS Version 10.15.7 (Build 19H1519) Xcode 12.4 (17801) (Build 12D4e) Timestamp: 2022-02-24T20:05:09-03:00
0
0
749
Mar ’22
Append a dictionary array to another dictionary array in Swift
have two quote dictionaries I'm trying to append after an in-app purchase. I have tried several different methods to append the dictionaries together but I'm still getting an error "No exact matches in call to instance method 'append'" I have established variables for each array to then append the array within the struct. Any thoughts? Is there a better method I should use to add the quotes from the array called QuoteDetails2 to the initial array QuoteDetails? Here is the code I'm trying to correct: var topQuotes = [QuoteDetails]() var additionalQuotes = [QuoteDetails2]() public struct QuoteProvider { static func all() -> [QuoteDetails] { return [ QuoteDetails( id: “1”, texts: “High school is fun”, authors: “SM” ), QuoteDetails( id: “2”, texts: “Middle School is fun”, authors: "A. Philip Randolph" ), QuoteDetails( id: “3”, texts: “The playground is fun”, authors: "Booker T. Washington" ), QuoteDetails( id: “4”, texts: "Hold on to your dreams of a better life and stay committed to striving to realize it.", authors: “KJ” ) ] } static func all2() -> [QuoteDetails2] { return [ QuoteDetails2( id: "1", texts: "The cat ran fast”, authors: " ME” ), QuoteDetails2( id: "2", texts: “The dog ran fast.”, authors: " ME” ), QuoteDetails2( id: "3", texts: "End life problems”, authors: “ME” ) ] } func showPremiumQuotes() { if UserDefaults.standard.bool(forKey: "premiumQuotes") == true { topQuotes.append(contentsOf: additionalQuotes) } } /// - Returns: A random item. static func random() -> QuoteDetails { let allQuotes = QuoteProvider.all() let randomIndex = Int.random(in: 0..<allQuotes.count) return allQuotes[randomIndex] } }
0
0
1.1k
Mar ’22
NSPersistentCloudKitContainer exclude relationship from share
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-share 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?
1
0
991
Feb ’22
Trouble with WWDC21 sample code for CloudKit
Hey all, I've just taken Xcode 13 Beta 2, and I still can't get the sample code from the "Sharing-Data" code to work properly, and nor does the boilerplate code from creating a new project that incorporates CodeData and CloudKit work. Fo far my feedback items have not been identified as having other similar issues - based on the posts I'm seeing I'm not the only one experiencing the same problem. Has anyone got this code built and working yet? Mine breaks when you try to copy the sharing link.
4
0
1.6k
Jan ’22
iOS 15 simulator vs. Cloudkit sharing invites
I am running the WWDC21 sample application "CoreDataCloudkitDemo" with two different Apple IDs to test the Cloudkit sharing feature. I use two simulators and one real device, where the latter has the same ID as one of the simulators. While creating invites via "Copy link" works on all three installations, accepting invites only works on the real device. Trying to open an invite (by copying the link in the one and pasting it into Safari in the other) always results in a web page stating that "iCloud has stopped responding" and "Unable to find applicationIdentifier for the containerId = [my ID] and fileExtension = undefined". Is this a simulator bug in Xcode 13.2 or is there anything I can do about it? Other iCloud features (including login via Safari to icloud.com) work in both simulators. Is there a way to open invite URLs in a simulator (as there is no functioning iMessage or Mail app) other than Safari's URL input field? Doing so does not work in the real device either, but clicking it in e.g. iMessage works. Edit: Pasting the link into a ToDo item and opening it from there works even in the simulator - so is it just a Safari issue?
0
0
1.3k
Jan ’22
About relationship in CoreData-CloudKit Share
Now, when using NSPersistentCloudKitContainer.share(_ managedObjects: [NSManagedObject], to share: CKShare?), A deep traversal will be performed among the objects and any related objects will also be shared. For example, if there are 100 posts with the same tag, I shared one of them, and the remaining 99 will be shared at the same time. Is there any way to control whether the relationship should be shared?
0
0
1.3k
Dec ’21
Share RecordZones or ParentRecords in CoreData-CloudKit Share
Hello everyone, in the App I'm building I'd like to share an entire list of items (records) by just sharing the list itself (parent record or RecordZone). Meanwhile, I'd like to continue using the NSPersistentCloudKitContainer and therefore CoreData sync. Is it possible, with the new features Apple introduced (Sharing RecordZone and Sharing in Cloud & Local Storage), to do what I described, and combine both functions. Thank you, Carlos Steiner
0
0
773
Dec ’21
Core Data Sharing with iCloud Drive Files
I have an app for client management that stores data in Core Data with an NSPersistentCloudKitContainer. Each manager have their clients in the Core Data Private Database, and each client could have associated files (images, documents, etc) that are stored in app's own folder structure in iCloud Drive. Eventually, a manager can decide if to share a client with another manager, in order to have a shared managed client (readable, or writable+readable by others managers which share the same client). This is done by moving the Client from the Private Database to the Shared Database following the Apple's guidelines: https://developer.apple.com/videos/play/wwdc2021/10015/ This is the structure: The problem is: the database record is shared correctly, but the iCloud Drive Files are not shared (obviously). My goal is to get working the iCloud Drive Client Files (every client has a single Folder) with the minimum effort from the user. I cannot get working the iCloud Drive Sharing from my app, only the Core Data Sharing, so (in development environment) I have to share the Client Core Data Info from the App sheet, and then, go to Finder and share the Client's folder and send the link, so it would be a bit confusing for my users. Any approach for get working iCloud Drive File Sharing from the (inside) my app? Generate a link and automatically send to the other user. Or, better, an approach to get working this sharing with a single action from the user (only share once, and it sends the core data info and icloud drive file sharing).
0
0
942
Oct ’21
How is Record Zone Sharing done?
My use case is the following: Every user of my app can create as an owner a set of items.  These items are private until the owner invites other users to share all of them as participant. The participants can modify the shared items and/or add other items. So, sharing is not done related to individual items, but to all items of an owner. I want to use CoreData & CloudKit to have local copies of private and shared items. To my understanding, CoreData & CloudKit puts all mirrored items in a special zone „com.apple.coredata.cloudkit.zone“. So, this zone should be shared, i.e. all items in it. In the video it is said that NSPersistentCloudKitContainer uses Record Zone Sharing optionally in contrast to hierarchically record sharing using a root record. But how is this done? Maybe I can declare zone „com.apple.coredata.cloudkit.zone“ as a shared zone?
Replies
2
Boosts
0
Views
1.2k
Activity
Apr ’25
CoreData: debug: PostSaveMaintenance: fileSize 30409752 greater than prune threshold
Dear: Use core data to store super long strings. After storage, the strings are incomplete. Xcode tips: CoreData: debug: PostSaveMaintenance: fileSize 30409752 greater than prune threshold CoreData: annotation: PostSaveMaintenance: wal_checkpoint(TRUNCATE)  help me?
Replies
3
Boosts
0
Views
3.8k
Activity
Jan ’24
Thread 1: "-[entity_name relation_name]: unrecognized selector sent to instance 0x600003812bc0"
I'm finding this issue after making sure I create an entity with the correspondent attribute. This issue comes from a relation between 2 entities: GroupData and TopicData. Their relations are like shown in the screenshots. Then, I get the context from a function like the next one. Every time I need to use the context, I call this function. import CoreData class DataController: ObservableObject {     let container = NSPersistentContainer(name: "vocabul-R")     init() {         container.loadPersistentStores { description, error in                 if let error = error {                     print("CoreData failed to load: \(error.localizedDescription)")                 }         }         container.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump         container.viewContext.retainsRegisteredObjects = true     } } I first create the objects from data I get from csv files. By debugging I've made sure that the objects created have the correspondent values for each attribute and the correct objects in relations.     guard let filepath = Bundle.main.path(forResource: data_file, ofType: "csv") else {         return     }     let dataController = DataController()     let context = dataController.container.viewContext     do {         try context.save()         }     catch {     }     var data = ""     do {         data = try String(contentsOfFile: filepath)     } catch {         return     }     var rows = data.components(separatedBy: "\n")     rows.remove(at: 0)     for row in rows {         let columns = row.components(separatedBy: ",")         let name = columns[0]         let activation_level = (columns[1] as NSString).integerValue         let activated: Bool = false         let last_opened_group: Int16 = 0         let current_level: Int16 = 0         let topic = TopicData(context: context)         topic.name = name         topic.activated = activated         topic.activationLevel = Int16(activation_level)         topic.last_opened_group = last_opened_group         topic.current_level = current_level         do {             try context.save()             }         catch {             print("Context not saved")         }     } } func parseCSV_groups (data_file: String, topic_name: String) {     guard let filepath = Bundle.main.path(forResource: data_file, ofType: "csv") else {         return     }     var data = ""     do {         data = try String(contentsOfFile: filepath)     } catch {         return     }     var rows = data.components(separatedBy: "\n")     rows.remove(at: 0)     let dataController = DataController()     let context = dataController.container.viewContext     let topic = TopicData.getTopicFromName(name: topic_name, context: context)     let train_list = Train_list(context: context)     let test_list = Test_list(context: context)     train_list.train_list = "train_list"     test_list.test_list = "test_list"     for row in rows {         let columns = row.components(separatedBy: ",")         let index_group = (columns[0] as NSString).integerValue         let mean_level = (columns[1] as NSString).integerValue         let cleared_words: Int16 = 0         let group = GroupData(context: context)         group.index_group = Int16(index_group)         group.mean_level = Int16(mean_level)         group.cleared_words = cleared_words         //group.topic = topic         topic.addToGroup(group)         do {             try context.save()             }         catch {             print("Context not saved")         }     } } I have created objects from both entities with relations. I have other functions with relations between these and other entities seem to work fine. But now I need to get all the groups that one TopicData object has. For that, I first get a topic from its name.         let fetchRequest = NSFetchRequest<TopicData>(entityName: "TopicData")         fetchRequest.predicate = NSPredicate(format: "name = %@", name)         let topics = (try? context.fetch(fetchRequest)) ?? []         let topic = topics.first ?? TopicData()         return topic     } This seems to work fine as I can print the topic name and the object type (which is TopicData). But then I try to get the groups that it has. I've also tried to get the groups with a fetchRequest     /fetchRequest.predicate = NSPredicate(format: "topic = %@", topic)     let groups = (try? context.fetch(fetchRequest)) ?? [] And when I try to get one of the attributes (activated) of one of these topics, I also get an error. I thought this could be happening because every time I use a topic to update it and save it on context again, a new topic is created which may not be related to GroupData. But I added a constraint in TopicData for name and I still get the same error. Another thing I thought is that relations could be disappearing, since I saw some people had this problem and the issue was that. But I added the retainsRegisteredObjects line in DataController and it didn't work. The full error I get is: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TopicData group]: unrecognized selector sent to instance 0x600003812bc0' terminating with uncaught exception of type NSException I think that is all about the problem. Any idea of what could be happening? I think I added everything relevant for the problem, but let me know if there is some other code I should add. Thank you!
Replies
3
Boosts
0
Views
1.3k
Activity
May ’22
Error: Unrecognised selector sent to instance
I'm getting this error because it seems the database forgets objects relations. I always use the same context (with different instances on each function), so I think I can't do anything with mutableSetValue. Also, I've tried to set retainsRegisteredObjects, but it doesn't seem to improve anything. An option I was thinking about is always using the same context and send it from one function to the next one, but it doesn't feel like that's an optimal solution. And I'm not sure if relations would stay after I closed the app, which is something I need. Any ideas of how to solve this issue?
Replies
3
Boosts
0
Views
684
Activity
May ’22
NSPersistantCloudkitContainer record modification outside of UICloudSharingController
I’m new to trying to modify share records and not having any luck with it. Somehow, I’ve made it such that every new coredata record I create is already listed as shared and accepted by another user (my other sandbox). This user never got a link nor has the record. I’d like to correct that issue. But hacking away at it, I can’t find a solution or even know what caused this. I assume I need to modify the record of the privateCloudDatabase?
Replies
0
Boosts
0
Views
1.1k
Activity
May ’22
NSPersistentCloudKitContainer Bug
I have been excited to add NSPersistentCloudKitContainer's share functionality to my app but I've noted a few thing I suspect are bugs: -When using share() on a NSManagedObject the share record is set up in a new zone. However, the root NSManagedObject's record is not being updated with the relationship linkage to the shared record. -Secondly, when you revoke a share, the cloudkit.share record is removed from iCloud, but not in the local data stores. This makes the fetchShares() method ineffective for detecting a missing cloudkit.share record. In order to re-share the root object the developer must call out to iCloud directly using the old methods to be sure if the share exists or not. I am using the code from Apple's 'Synchronizing a Local Store to the Cloud' sample. It would be nice if they added support for revoking shares into this sample and addressed these issues.
Replies
8
Boosts
0
Views
6.1k
Activity
Apr ’22
Deleting a Share without deleting Objects
Hi, I wanted to offer the UI for editing and deleting a share. So for using UICloudSharingController(share: , container: ) I implemented the delegate to call "persistUpdatedShare" in "cloudSharingControllerDidSaveShare" func cloudSharingControllerDidSaveShare(_ csc: UICloudSharingController) { if let share = csc.share,   let privatePersistentStore = PersistenceController.shared.privatePersistentStore { PersistenceController.shared.container.persistUpdatedShare(share, in: privatePersistentStore) { (share, error) in Thread.performOnMain { if let error = error { PersistenceController.shared.storeWarning = error } } } } } and to call "purgeObjectsAndRecordsInZone" in "cloudSharingControllerDidStopSharing" func cloudSharingControllerDidStopSharing(_ csc: UICloudSharingController) { let puzzleToShare = puzzleToShare if let share = csc.share,   let privatePersistentStore = PersistenceController.shared.privatePersistentStore { PersistenceController.shared.container.purgeObjectsAndRecordsInZone(with: share.recordID.zoneID, in: privatePersistentStore) { (zoneID, error) in Thread.performOnMain { if let error = error { PersistenceController.shared.storeWarning = error } else { puzzleToShare.makePrivateDuplicate() try? puzzleToShare.puzzle.managedObjectContext?.save() } } } } } I got this implementation from a TSI, but it makes no sense to me to delete and duplicate my objects rather than just keeping them and only deleting the share. Question: How can I cleanly discontinue a share, but keep my data. Duplicating my objects seems such a weird approach. But without this implementation it does not really work. (I get strange behaviors and crashes) All the best Christoph
Replies
1
Boosts
0
Views
1.2k
Activity
Mar ’22
CloudKit - Problems with template application
G'day everyone, I've had some problems with CoreData+CloudKit, and figured I would go back to basics and start from scratch with a new project. (Note: I'm using the Xcode 13.0 Beta with iOS 15 to try to use sharing on NSPersistentCloudKitContainer as discussed in WWDC2021, but these problems are scattered over the net without any answers to date) When I go through the motions of adding iCloud to the project, assign a new (unique) container and then build the app, two problems arise: the simulator comes back with a blank screen (without the Edit or add controls from the boilerplate). Even the preview pane seems broken (no "Add Item" button). This worked in Xcode 12, so I am assuming there is something that's come up as a bug here. More importantly, I get a swath of errors and warnings in the debug console related to CloudKit. It looks like there is some sort of identity problem here. There is no schema generated as yet in the CloudKit dashboard, so I am guessing that the migration errors are happening because the database hasn't yet established because of the identify problem. Does anyone have any insight into what I'm missing here? Thanks.
Replies
7
Boosts
0
Views
2.6k
Activity
Mar ’22
How to properly "Delete a row from a tableView" using trailingSwipeActionsConfiguration
I have been stuck on this for some time now, I built a tableView App with the ability to delete a row. I am using with CoreData and iCloud. When I use "editActionsForRowAt" it deletes from the view and does not re-appear when I close and run the App again, the problem is as you know it is deprecated in iOS 13. 1.) This works great but is deprecated in iOS 13 override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? { //Social Sharing Button let shareAction = UITableViewRowAction(style: UITableViewRowAction.Style.default, title: "share", handler: { (action, indexPath) -> Void in _ = "Just checking in at " + self.inspections[indexPath.row].stateID! }) // Delete Button let deleteAction = UITableViewRowAction(style: UITableViewRowAction.Style.default, title: "Delete",handler: { (action, indexPath) -> Void in if let appDelegate = (UIApplication.shared.delegate as? AppDelegate) { let context = appDelegate.persistentContainer.viewContext let inspectionsToDelete = self.fetchResultController.object(at: indexPath) context.delete(inspectionsToDelete) appDelegate.saveContext() } }) deleteAction.backgroundColor = UIColor(red: 237.0/255.0, green: 66.0/255.0, blue: 106.0/255.0, alpha: 1.0) shareAction.backgroundColor = UIColor(red: 63.0/255.0, green: 212.0/255.0, blue: 78.0/255.0, alpha: 1.0) return [deleteAction, shareAction] } 2.) So I ran with "trailingSwipeActionsConfigurationForRowAt" This should work but it will not swipe to delete the row. func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationsForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let deleteAction = UIContextualAction(style: .normal, title: "Delete", handler: {(action, view, success) in if let appDelegate = (UIApplication.shared.delegate as? AppDelegate) { let context = appDelegate.persistentContainer.viewContext let inspectionsToDelete = self.fetchResultController.object(at: indexPath) context.delete(inspectionsToDelete) appDelegate.saveContext() } }) return UISwipeActionsConfiguration(actions: [deleteAction]) } 3.) This deletes without 1.) or 2.) but repopulates the row when I reopen the App override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete { // delete the row from the data source inspections.remove(at: indexPath.row) } tableView.deleteRows(at: [indexPath], with: .fade) }
Replies
2
Boosts
0
Views
1.5k
Activity
Mar ’22
Unable to handle conflict reported by NSCloudKitMirroringDelegate
I'm working on an app that uses NSPersistentCloudKitContainer to handle CloudKit sharing. Against all odds I've gotten the sharing to work, but now I'm seeing errors on startup that look very much like some kind of background loop trying to merge changes from multiple users and failing. In a more traditional CloudKit installation not backed on NSPersistentCloudKitContainer this feels like a case where I'd have to provide some code to handle the merge. In the brave new world I can't seem to find anyway to affect this Mirroring Delegate. It starts when I initialize the NSPersistentCloudKitContainer and produces the error below (as well as a long stream of similar errors). Any ideas? error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _exportFinishedWithResult:exporter:](1347): <PFCloudKitExporter: 0x282d2ead0>: Export failed with error: <CKError 0x280079470: "Partial Failure" (2/1011); "Failed to modify some records"; partial errors: { cloudkit.zoneshare:(Pacts:__defaultOwner__) = <CKError 0x280079680: "Server Record Changed" (14/1022); "Participants conflict while trying to update share from the server. Participants: === Client: (     "<CKShareParticipant: 0x100cebb70; participantID=..., isCurrentUser=true, role=owner, permission=readWrite, acceptanceStatus=Accepted, identity=<CKUserIdentity: 0x100c4cae0; userID=__defaultOwner__:(_defaultZone:__defaultOwner__), nameComponents=, cached=false, publicKeyVersion=2>, hasProtectionInfo=true, invitationTokenStatus=Healthy, isAnonymousInvitedParticipant=false>" ) === Server: (     "<CKShareParticipant: 0x100c26db0; participantID=..., isCurrentUser=true, role=owner, permission=readWrite, acceptanceStatus=Accepted, identity=<CKUserIdentity: 0x100c13b60; userID=__defaultOwner__:(_defaultZone:__defaultOwner__), nameComponents=..., lookupInfo=<CKUserIdentityLookupInfo: 0x100c13c00; email=...>, cached=false, publicKeyVersion=2>, hasProtectionInfo=true, invitationTokenStatus=Healthy, isAnonymousInvitedParticipant=false>",     "<CKShareParticipant: 0x100c25960; participantID=..., isCurrentUser=false, role=user, permission=readWrite, acceptanceStatus=Accepted, identity=<CKUserIdentity: 0x100c259f0; userID=_6cd4c7c8091c946d4b8e704efbfc0bc4:(_defaultZone:__defaultOwner__), nameComponents=..., lookupInfo=<CKUserIdentityLookupInfo: 0x100c68d10; email=...>, cached=false, publicKeyVersion=2>, hasProtectionInfo=true, invitationTokenStatus=Healthy, isAnonymousInvitedParticipant=false>" )"> }>
Replies
1
Boosts
0
Views
1.1k
Activity
Mar ’22
automatic update for @FetchedResults
Hi, I always though @FetchedResults should automatically update, but it seems this is not always true, or do I have to trigger updates myself? I am using Core Data with CloudKit sync. When I start my app, nothing is visually updating while it'S doing the first sync. Only after that view is reloaded it shows the synced data. Any idea what I have to do automatically get updates when the data is syncing the background. All the best Christoph
Replies
1
Boosts
0
Views
1.2k
Activity
Mar ’22
Error start simulator Xcode
Hi, I'm building and when it start the app install in the simulator, this error happens Domain: NSPOSIXErrorDomain Code: 53 Failure Reason: Software caused connection abort -- System Information macOS Version 10.15.7 (Build 19H1519) Xcode 12.4 (17801) (Build 12D4e) Timestamp: 2022-02-24T20:05:09-03:00
Replies
0
Boosts
0
Views
749
Activity
Mar ’22
Append a dictionary array to another dictionary array in Swift
have two quote dictionaries I'm trying to append after an in-app purchase. I have tried several different methods to append the dictionaries together but I'm still getting an error "No exact matches in call to instance method 'append'" I have established variables for each array to then append the array within the struct. Any thoughts? Is there a better method I should use to add the quotes from the array called QuoteDetails2 to the initial array QuoteDetails? Here is the code I'm trying to correct: var topQuotes = [QuoteDetails]() var additionalQuotes = [QuoteDetails2]() public struct QuoteProvider { static func all() -> [QuoteDetails] { return [ QuoteDetails( id: “1”, texts: “High school is fun”, authors: “SM” ), QuoteDetails( id: “2”, texts: “Middle School is fun”, authors: "A. Philip Randolph" ), QuoteDetails( id: “3”, texts: “The playground is fun”, authors: "Booker T. Washington" ), QuoteDetails( id: “4”, texts: "Hold on to your dreams of a better life and stay committed to striving to realize it.", authors: “KJ” ) ] } static func all2() -> [QuoteDetails2] { return [ QuoteDetails2( id: "1", texts: "The cat ran fast”, authors: " ME” ), QuoteDetails2( id: "2", texts: “The dog ran fast.”, authors: " ME” ), QuoteDetails2( id: "3", texts: "End life problems”, authors: “ME” ) ] } func showPremiumQuotes() { if UserDefaults.standard.bool(forKey: "premiumQuotes") == true { topQuotes.append(contentsOf: additionalQuotes) } } /// - Returns: A random item. static func random() -> QuoteDetails { let allQuotes = QuoteProvider.all() let randomIndex = Int.random(in: 0..<allQuotes.count) return allQuotes[randomIndex] } }
Replies
0
Boosts
0
Views
1.1k
Activity
Mar ’22
NSPersistentCloudKitContainer exclude relationship from share
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-share 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?
Replies
1
Boosts
0
Views
991
Activity
Feb ’22
Trouble with WWDC21 sample code for CloudKit
Hey all, I've just taken Xcode 13 Beta 2, and I still can't get the sample code from the "Sharing-Data" code to work properly, and nor does the boilerplate code from creating a new project that incorporates CodeData and CloudKit work. Fo far my feedback items have not been identified as having other similar issues - based on the posts I'm seeing I'm not the only one experiencing the same problem. Has anyone got this code built and working yet? Mine breaks when you try to copy the sharing link.
Replies
4
Boosts
0
Views
1.6k
Activity
Jan ’22
Change ViewController background different colors for single button tapped
Ok, so like I want to have the background be red then press a button to change it to green then press the same button to change it to yellow. How could I do this?
Replies
0
Boosts
0
Views
695
Activity
Jan ’22
iOS 15 simulator vs. Cloudkit sharing invites
I am running the WWDC21 sample application "CoreDataCloudkitDemo" with two different Apple IDs to test the Cloudkit sharing feature. I use two simulators and one real device, where the latter has the same ID as one of the simulators. While creating invites via "Copy link" works on all three installations, accepting invites only works on the real device. Trying to open an invite (by copying the link in the one and pasting it into Safari in the other) always results in a web page stating that "iCloud has stopped responding" and "Unable to find applicationIdentifier for the containerId = [my ID] and fileExtension = undefined". Is this a simulator bug in Xcode 13.2 or is there anything I can do about it? Other iCloud features (including login via Safari to icloud.com) work in both simulators. Is there a way to open invite URLs in a simulator (as there is no functioning iMessage or Mail app) other than Safari's URL input field? Doing so does not work in the real device either, but clicking it in e.g. iMessage works. Edit: Pasting the link into a ToDo item and opening it from there works even in the simulator - so is it just a Safari issue?
Replies
0
Boosts
0
Views
1.3k
Activity
Jan ’22
About relationship in CoreData-CloudKit Share
Now, when using NSPersistentCloudKitContainer.share(_ managedObjects: [NSManagedObject], to share: CKShare?), A deep traversal will be performed among the objects and any related objects will also be shared. For example, if there are 100 posts with the same tag, I shared one of them, and the remaining 99 will be shared at the same time. Is there any way to control whether the relationship should be shared?
Replies
0
Boosts
0
Views
1.3k
Activity
Dec ’21
Share RecordZones or ParentRecords in CoreData-CloudKit Share
Hello everyone, in the App I'm building I'd like to share an entire list of items (records) by just sharing the list itself (parent record or RecordZone). Meanwhile, I'd like to continue using the NSPersistentCloudKitContainer and therefore CoreData sync. Is it possible, with the new features Apple introduced (Sharing RecordZone and Sharing in Cloud & Local Storage), to do what I described, and combine both functions. Thank you, Carlos Steiner
Replies
0
Boosts
0
Views
773
Activity
Dec ’21
Core Data Sharing with iCloud Drive Files
I have an app for client management that stores data in Core Data with an NSPersistentCloudKitContainer. Each manager have their clients in the Core Data Private Database, and each client could have associated files (images, documents, etc) that are stored in app's own folder structure in iCloud Drive. Eventually, a manager can decide if to share a client with another manager, in order to have a shared managed client (readable, or writable+readable by others managers which share the same client). This is done by moving the Client from the Private Database to the Shared Database following the Apple's guidelines: https://developer.apple.com/videos/play/wwdc2021/10015/ This is the structure: The problem is: the database record is shared correctly, but the iCloud Drive Files are not shared (obviously). My goal is to get working the iCloud Drive Client Files (every client has a single Folder) with the minimum effort from the user. I cannot get working the iCloud Drive Sharing from my app, only the Core Data Sharing, so (in development environment) I have to share the Client Core Data Info from the App sheet, and then, go to Finder and share the Client's folder and send the link, so it would be a bit confusing for my users. Any approach for get working iCloud Drive File Sharing from the (inside) my app? Generate a link and automatically send to the other user. Or, better, an approach to get working this sharing with a single action from the user (only share once, and it sends the core data info and icloud drive file sharing).
Replies
0
Boosts
0
Views
942
Activity
Oct ’21