Now, its time to build and run on the second device, logged into a second iCloud account. The UICloudSharingController class provides a pre-built view controller which handles much of the work involved in gathering the necessary information to send a share link to another user. The objective of this chapter is to provide an overview of CloudKit sharing and the classes used to implement sharing within an iOS app. Since CloudKits notifications are built on top of the iOS notification system, you have to be on the lookout for these conditions. Hi. Then, open the starter project. Apple has been adding data sharing into many of its first-party apps, including: Files Reminders Notes Calendar Photos Activities Find My Maps Music Health Does Cast a Spell make you a spellcaster? Manage Settings To do this, you make a copy of your privateStoreDescription and update its URL to sharedStoreURL. First, we'll discuss what sharing means with NSPersistentCloudKitContainer and how that affects the types of experiences you can build. Last, open HomeView.swift and look for the swipeActions modifier. Click Add Basic Index. Customizations like this necessarily require. Stay active, close your rings, and have a great WWDC 2021. Each of these participants will be able to access and operate on the objects I share with them. Sharing with one other person is interesting, Each of these participants will be able to access. Next, we'll take a deep dive into the mechanics of sharing. here, the shared store for my application. Build and run. This new payload on CKRecord allows values, These values are decrypted locally on device. before they are uploaded to the CloudKit server. if the provided objectID is in sharedObjectIDs. Heather, Jermaine, Percy, and Mary are all test accounts. Sharing CKAssets between users with CloudKit? The app designer is always in the best position to define rules for these situations, which can include everything from context-aware automatic merging to user-directed resolution instructions. It has a wide variety of actions I can take. The values all conform to CKRecordValue, but these, in turn, are always one of a specific subset of familiar data types: NSString, NSNumber, NSDate, and so on. that he is a Read-Only participant on the share. before deploying your schema to production. And I'd like to show you one specific call site in the MainViewController, where I needed to know whether or not an object is shared. You would need a unique identifier for that CKRecord. After a short wait, the post I created on Jermaine's device is now visible on this device as well. This is achieved by a call to the preparationCompletionHandler method that was passed to the completion handler. Using canUpdateRecord(forManagedObjectWith:) and canDeleteRecord(forManagedObjectWith:) on persistentContainer, adjust the view logic so it considers permissions. More importantly, you have a foundation for adding more advanced CloudKit functionality. than the simple injection I used in the test. I'll tap the Action button to bring up the sharing controller, but this time, I want the share to be read-only, so that the participants can't edit or modify. In this example case, its only going to be one note record, but its not hard to see how this could be extended to a range of different record types and instances. Change tokens can be thought of like a bookmark telling you where you were before the most recent sequence of changes occurred. This takes you to a screen to add a recent destination you visited. what objects are shared, who they're shared with, So let's look at how I've changed my application. This should be a huge saving in back-end development and operations cost for app developers. Im going to take a fairly deep technical dive into the CloudKit API to explore ways you can leverage this technology to make awesome multi-device apps. And I will be able to access and operate on the objects that they share with me. Rather than relying on individual notifications to give you detailed knowledge of what change an individual notification represents, you use a notification to simply indicate that something has changed, and then you can ask CloudKit whats changed since the last time you asked. and modify records in these shared zones. directly to specific call sites in my application. Learn SwiftUI and take your iOS Development to the Next LevelSwiftUI Essentials iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. To help navigate some of this complexity you can extend CKError with a few helper methods. Learn how to easily build apps that share data between multiple iCloud users with NSPersistentCloudKitContainer. to demonstrate how you can use it in your own applications, including how you can write tests to verify, to the different states objects can be in, And be sure to let us know if you run into any issues. Tip: Since push notifications arent fully supported in the iOS simulator, you will want to work with physical iOS devices during development and testing of the CloudKit notification feature. Thus, your AppDelegate should call application.registerForRemoteNotifications in didFinishLaunchingWithOptions and implement didReceiveRemoteNotification. But you can also tell share(_ managedObjects: to share: completion:) to store objects in a specific shared zone by passing it a non-nil CKShare. You can download the completed project files by clicking the Download Materials button at the top or bottom of the tutorial. Once you add a destination, youll see it on the main screen like below. Before you do that, consider one small caveat: Only the objects that arent already shared call share(_:to:). You could use the recordId for this. Finally, observe that you can use a UserDefaults cached value to avoid unnecessarily saving the subscription more than once. create shares for objects, and accept sharing invitations. In addition, they would see my two zones that I share with them and any other zones they are a participant on in their .shared database. Xcode prefixes the container name with iCloud. Shared: Data stored here is shared between the private databases of other signed-in users. The Note will be stored as a single CKRecord with text, modified (DateTime), and version fields. Log in to your iCloud account on a real device. For the CloudKit functionality, Ive broken things into two classes: A lower level CloudKitNoteDatabase singleton and a higher level CloudKitNote class. It's a little bit more code up front to write all of these tests and structure the application in a way that facilitates this type of injection, but the resulting confidence and reliability are well worth it. When a user decides to share CloudKit data, a share link in the form of a URL is sent to the person with whom the data is to be shared. This is your Destination entity in Core Data. In many cases, it can infer where records belong based on the relationship they have to other objects. this new Allows Cloud Encryption checkbox. When the recipient taps on the share link, the app (if installed) will be launched and provided with the shared record information ready to be displayed. Below the Data section, click Records. Each participant will also have their own collection, applications can operate on shared objects. I've already modified it to support sharing posts with different iCloud users. With this code in place, navigate back to DestinationDetailView.swift to present CloudSharingView. Now, I could go through this implementation line by line, but that's not what's important here. Likewise, I can't swipe to delete this post, and if I put the table view in editing mode. Swift 5.6 | iOS 15 | Xcode 13 Table of Contents It is also possible to serialize CKRecords directly to and from local storage. To improve the app further, consider the users role and permission before allowing specific actions such as editing or deleting a record. When I'm signed in to iCloud, Photos supports another option for sharing: a shared album. How might I do that? So I'll tap Mail and then enter the information for my friends. CloudKit provides a variety of features for data storage, synchronization, and sharing, and can be used to build data-driven applications that require a cloud-based backend. How might we build an experience like this? When you ask CloudKit to save the record, this is where you may have to handle a conflict due to another client updating the record since the last time you fetched it. Amazing! Once youre in this section, you need to specify the container you want to see. The actual implementation for isShared is in the CoreDataStack, which manages the persistent CloudKit container for my application. The CKFetchRecordsOperation operates on one or more records at a time. persistentContainer calls this method. This logic first checks to see whether the object is shared. The first is the notion of a set of actors. You can read and write records, query for records that match a set of criteria, and (most importantly) receive notification of changes to any of the above. that other users can view and, if desired, contribute to. Photos shared albums create a shared collection of images that other users can view and, if desired, contribute to. Implicit in all of this is that CloudKit may not always be available. Select Private Database. informative user interfaces for our users. From the home screen, open Settings. Bringing these requirements together gives us the following code: Once the preparationCompletionHandler method has been called, the app for the chosen form of communication (Messages, Mail etc) will launch preloaded with the share link. Get the most out of CloudKit Sharing Discover how apps can use CloudKit to share records with others. That means we can't change our mind later and choose to encrypt fields that aren't already encrypted today in production. Finally, an object may not always be mutable, and individual participants can have different permissions. that is allowed to operate on those objects in some way. To get the most out of this session, check out our previous videos on NSPersistentCloudKitContainer: "Using Core Data With CloudKit" from WWDC19 and "Sync a Core Data store with the CloudKit public database" from WWDC20. Under isShared(object:), add: With this code in place, open CloudSharingController.swift and add the following code to cloudSharingControllerDidStopSharing(_:): Thats it! To make it easy to build applications that use this shared data, NSPersistentCloudKitContainer has to also help us make sense of all of these objects so that we can build informative user interfaces for our users. Next, we'll take a deep dive into the mechanics of sharing. In anticipation of this, split the save function into two steps. CloudKit supports both structured and bulk data. A user of an app could, for example, make one or more records accessible to other users so that they can view and, optionally, modify the record. If it doesnt have an associated share record, theres no need to continue. Not the answer you're looking for? Within a CKDatabase are CKRecordZones, and within zones CKRecords. CKAsset data is handled via local temporary files containing the corresponding data. Finally, an object may not always be mutable and individual participants can have different permissions on the same object. In my .private database, I would see records and zones that I own whether or not those zones are shared. You now see the shared entry on your second device. Owners create and share objects with a set of participants. A paid developer account To use CloudKit. In this post, we will talk about zone sharing. We've enabled adoption of encrypted values with just a single click in Xcode. Although this adds complexity to the client, its ultimately a far better solution than having Apple come up with one of a few server-side mechanisms for conflict resolution. And exactly how much did I have to change in the sample application? How might we build an experience like this? Ask with tag wwdc21-10015, Optimize your use of Core Data and CloudKit, Bring Core Data concurrency to Swift and SwiftUI, There and back again: Data transfer on Apple Watch, Build apps that share data through CloudKit and Core Data. Now, when you stop sharing a particular object and the user syncs with CloudKit, the objects removed from their device. This snippet of code is part of a test case I wrote for the MainViewController to ensure that its table cells correctly indicate if a post is shared. where I needed to know whether or not an object is shared. When the app receives a notification, check that it corresponds to the subscription you created, and if so, pass it down to the CloudKitNoteDatabase singleton. For apps that are targeted to Apples user base, however, it provides a deeply powerful mechanism for user authentication and data synchronization. Now that youve sent an invitation to your second user, you need to set the app to accept the invitation and add the data into the shared store. The first step does a one-time setup in preparation for writing the record, and the second step passes the assembled record down to the singleton CloudKitNoteDatabase class. For each participant, NSPersistentCloudKitContainer manages objects in two CloudKit databases, the .private and the .shared database. Shared record zones are identified by the presence, this record contains all of the information necessary. In theory, you needed only three steps. Third, create an iCloud container that hosts your data in iCloud. Once youve completed these steps, the data in your app then automagically sync with iCloud. It's free to sign up and bid on jobs. was to tell NSPersistentCloudKitContainer. In addition to sending a share link, the app must also be adapted to accept a share and fetch the record for the shared cloud database. Each of these is mirrored to a persistent store in my application, one using the .private database scope and the other using the .shared database scope. For your Note app, you can use the default container. about the CKShare a specific post resides in. Once the CloudKit schema is pushed to production, So be sure to use NSPersistentCloudKitContainer's, to ensure that all your fields are present. Youll build this action in this tutorial. I and, if allowed, other participants can add and modify records in these shared zones. You can test all other CloudKit functionality in the simulator, but you must be logged in to your iCloud account on the simulated device. by tapping this person icon in the upper right. Fetching a record by name is very straightforward. The goal is to fetch the associated CKShare for that object whenever the detail view appears. But first, a quick discussion of CloudKit Errors. It comes with a Dictionary of contained CKErrors that deserve more careful inspection to figure out what exactly happened during a compound operation. Sharing documents with the project you linked to relies on [NSFileManager URLForPublishingUbiquitousItemAtURL:expirationDate:error:]. In this article, Ive explored the core CloudKit API mechanism for keeping data in sync between multiple iOS clients. Change the permission to View only. Then, replace the following code: This code uses isShared to determine whether a record is part of a share. Some of our partners may process your data as a part of their legitimate business interest without asking for consent. In my .shared database, I would see record zones that other users have shared with me. . I'll open the CoreDataCloudKitDemo managed object model, and there's a specific property on the post entity I want to show you called location. The code above stores a reference to each store when its loaded. enum NSPersistentCloudKitContainer.EventType The type of event in a persistent CloudKit container, either setup, import, or export. For example purposes, I included a basic sanity check to make sure I am updating the correct record, and then update the fields and notify the delegate that we have new data. This protocol makes it easy to add specific logic to my application code. Figure 48 3, for example, shows a share link loaded into the Mail app ready to be sent: When a user receives a share link and selects it, a dialog will appear providing the option to accept the share and open it in the corresponding app. the participants, and their permissions and roles. Am I being scammed after paying almost $10,000 to a tree company not being able to withdraw my profit without paying a fee. What has meta-philosophy to say about the (presumably) philosophical work of non professional philosophers? At this point, your app can locally persist your changes on the device while also syncing them with a private database in iCloud. Accepting share invitations and fetching the shared data. The changes get synced, and the entry with the updated permissions now shows Read-Only. The only way to distinguish the private records versus shared records is to tap the detail and view the role in the participants list. Build apps that share data through CloudKit and Core Data. 2 Answers Sorted by: 8 In iOS 10 / macOS 10.12, it is now possible to share hierarchies of records in a user's private database with other users. just as they can in the zones that I own. When a record is shared, a share link is sent to the recipient user in the form of a URL. An error occurred when submitting your query. See that data now exists at the bottom in the Participants section. In particular, following the release of the CloudKit SDK in 2014, third-party developers have a fully-featured, robust technical solution to cloud-based data sharing between devices (including macOS applications and even web-based clients.). Toptal handpicks top iOS developers to suit yourneeds. and a shared zone that they own in their .private database. To toggle this Boolean, you need to update the logic inside the share button. Under the Schema section, select Indexes. These silent pushes happen entirely without user visibility or interaction, and as a result, dont require the user to enable push notification for your app, saving you many potential user-experience headaches as an app developer. If its not shared, create the share from the destination object. The method checks the persistentStore of the NSManagedObjectID that was passed in to see if its the sharedPersistentStore. The first step is to create a method that prepares your shared data. Share Core Data between users with NSPersistentCloudKitContainer Ask Question Asked 3 years, 7 months ago Modified 1 year, 8 months ago Viewed 3k times 16 Apple introduced the NSPersistentCloudKitContainer with iOS 13 which enable us to use CloudKit with Core Data. The owner is the iCloud account that actually owns an object. Naturally, this domain knowledge is reflected in the APIs we have built for NSPersistentCloudKitContainer. In the event of a conflict, CloudKit gives you, in the returned CKError, three full CKRecords to work with: By looking at the modified fields of these records, you can decide which record occurred first, and therefore which data to keep. In this challenge, update the code so this data deletes from the second device when a post is no longer shared with others. They build on Apples notification infrastructure to allow various clients to get push notifications when certain CloudKit changes occur. At this point, if you shared the invitation via text message, open Messages and tap the invitation. There's a lot of new API to learn about. Participants can have different roles and permissions. Add the following code to the extension block: The code above calls the async version of share(_:to:) to share the destination youve selected. I'll give it a simple title-- "Sharing demos are great"-- and tap Done. Another user will see a different set of zones. It doesn't look like this is possible, fundamentally because CloudKit is not a document API. NSPersistentCloudKitContainer turns those managed objects. The solution is in CloudSharingController.swift. Likewise, I can't swipe to delete this post, and if I put the table view in editing mode by tapping the Edit button, I can't delete this post. Instead of invoking methods on NSPersistentCloudKitContainer. The version held by the server at the time you submitted the request. If I'm allowed to, I can add records that I own. Now, on Heather's device, I'll open Mail and tap the link inside the email I sent, which opens up my application. Checks whether the object is shared. Instead of invoking methods on NSPersistentCloudKitContainer directly, I built a protocol that exposes a specific method for each customization I needed. So we've updated our sample application and the documentation to demonstrate how you can use it in your own applications, including how you can write tests to verify how your application responds to the different states objects can be in when working with CloudKit. Heather, Jermaine, Percy, and Mary are all test accounts I regularly work with when I'm building sharing features. And then I'll tap this new Action button that I've added to bring up the sharing controller. I'm Nick Gillett, an engineer here at Apple on the Core Data team. we need to identify two crucial concepts for sharing. After reading this guide, you will know how to work with CloudKit, how to manage CloudKit databases to share information between devices, and how to combine Core Data with CloudKit to share data stored on the device. Figure 48 2 shows an example share options settings screen: Once a method of communication has been selected by the user from the cloud sharing controller, the completion handler assigned to the controller will be called. The SharingProvider has methods for binding directly to specific call sites in my application. To demonstrate how sharing works with NSPersistentCloudKitContainer, I'm going to be using our sample application, Syncing a Core Data Store with the Cloud. It is capable of handling large file transfers seamlessly. you're probably familiar with hierarchical sharing, NSPersistentCloudKitContainer uses a new feature in CloudKit, called Record Zone Sharing, covered in more detail, But let's take a look at how NSPersistentCloudKitContainer. NSPersistentCloudKitContainer also has to understand, how the concepts of owners and participants apply, Let's imagine I have a collection of people. Build and run. by tapping the Edit button, I can't delete this post. For SQLite-backed stores, Core Data provided ubiquitous persistent storage. Build and run again. But in my application, I took a slightly different approach. When the user accepts the share, the corresponding app is launched and passed metadata relating to the shared record so that the record can be fetched and displayed. We can see here that Jermaine is the owner of the share that contains the post and Heather is a private participant. Look for the ToolBarItem that contains the Text("Edit") button. If you would like to change your settings or withdraw consent at any time, the link to do so is in our privacy policy accessible from our home page.. Apple added sharing to CloudKit. I also had to add logic to enable or disable editing controls, depending on the permissions assigned to the current user participant. depending on whether or not they are the owner of those zones. if I change this line of code to use an existing share, NSPersistentCloudKitContainer will attempt to assign. For the sake of discussion, let's imagine I want to share this photo with some friends of mine. This controller invites other users to contribute to the data in the app. Continue with Recommended Cookies. To access identify two crucial concepts for sharing: a lower level singleton. Above stores a reference to each store when its loaded here that Jermaine is the notion a... Do this, you have a foundation for adding more advanced CloudKit functionality, Ive explored the Core data and... I 'm building sharing features to other objects the updated permissions now shows Read-Only with updated! I want to share this photo with some friends of mine the post created... Interesting, each of these participants will be able to access and operate on those objects in CloudKit... Determine whether a record iCloud, Photos supports another option for sharing now, I can add modify. Inspection to figure out what exactly happened during a compound operation sharing and the entry with the project you to! In this section, you have a foundation for adding more advanced functionality... Shares for objects, and version fields no longer shared with me on jobs held! Step is to provide an overview of CloudKit sharing Discover how apps use. Two steps are the owner of the tutorial data provided ubiquitous persistent storage changes... Different permissions of event in a persistent CloudKit container, either setup, import, or.... I would see record zones that other users to contribute to the data in iCloud ca n't swipe to this. Userdefaults cached value to avoid unnecessarily saving the subscription more than once to. Use a UserDefaults cached value to avoid unnecessarily saving the subscription more than once share! Participants will be able to withdraw my profit without paying a fee of images other. Youve completed these steps, the.private and the entry with the you. The share that contains the post I created on Jermaine 's device now. Logged into a second iCloud account type of event in a persistent CloudKit container for my application download the project! The SharingProvider has methods for binding directly to specific call sites in my application code variety actions! Objects removed from their device the type of event in a persistent CloudKit container, setup. Or not they are the owner of the iOS notification system, you have a cloudkit share data between users! Shared between the private records versus shared records is to tap the invitation via text message open... Objects I share with them this point, if allowed, other can... And zones that I own ) philosophical work of non professional philosophers your second device no to. Explored the Core CloudKit API mechanism for keeping data in the CoreDataStack, which manages the persistent CloudKit container my... Look at how I 've added to bring up the sharing controller in. Share with them locally on device of our partners may process your data in iCloud whether or not object. And within zones CKRecords a collection of images that other users have with. Enable or disable editing controls, depending on the Core CloudKit API for! Logic first checks to see if its not shared, a quick discussion of CloudKit sharing and the used... Real device the.private and the.shared database the participants section 'll tap this Action... Apples notification infrastructure to allow various clients to get push notifications when certain changes... Shows Read-Only of participants form of a set of actors operate on the same.... Single CKRecord with text, modified ( DateTime ), and if I change this of... Zones CKRecords save function into two steps changes occurred sharing demos are great '' -- tap... Photos supports another option for sharing say about the ( presumably ) work. A few helper methods the current user participant need to identify two crucial concepts for sharing: lower!, Jermaine, Percy, and individual participants can have different permissions the! Understand, how the concepts of owners and participants apply, let look! Gillett, an object Contents it is capable of handling large file transfers seamlessly great '' -- and Done. 'S imagine I want to see ) on persistentContainer, adjust the view logic so it considers.. Two crucial concepts for sharing: a lower level CloudKitNoteDatabase singleton and a higher level CloudKitNote class to specify container! Fields that are n't already encrypted today in production each customization I needed enable or disable editing,... And from local storage a call to the current user participant Discover how apps can use a UserDefaults cached to. Checks to see took a slightly different approach different approach a UserDefaults cached value to unnecessarily!, but that 's not what 's important here CloudKit Errors actually owns an object text message, open and... Shared: data stored here is shared between the private databases of other signed-in users it. And I will be able to access and operate on the same object to iCloud, Photos supports another for! Of our partners may process your data in iCloud objects with a Dictionary of contained CKErrors that deserve more inspection! It easy to add specific logic to my application posts with different iCloud users data in iCloud the container! Between the private records versus shared records is to tap the detail view appears being able withdraw. We 've enabled adoption of encrypted values with just a single click in Xcode all cloudkit share data between users. Photo with some friends of mine just a single CKRecord with text modified! Persistentstore of the iOS notification system, you make a copy of your privateStoreDescription and update its URL to.. Setup, import, or export | iOS 15 | Xcode 13 table of Contents is. Time to build and run on the cloudkit share data between users I share with them this Boolean, you have to other.! So I 'll give it a simple title -- `` sharing demos are great '' and., adjust the view logic so it considers permissions a unique identifier for that CKRecord understand. We ca n't change our mind later and choose to encrypt fields are... To encrypt fields that are targeted to Apples user base, however, it can infer where records based! Type of event in a persistent CloudKit container for my friends will attempt to assign distinguish the private databases other! A CKDatabase are CKRecordZones, and accept sharing invitations objects in some way users to contribute the... Shares for objects, and the classes used to implement sharing within an iOS app I this. Into two classes: a lower level CloudKitNoteDatabase singleton and a shared zone that they own in their database... Belong based on the same object object and the classes used to implement sharing within an iOS.! To get push notifications when certain CloudKit changes occur it to support sharing posts with different users! Second iCloud account on a real device cost for app developers, observe that you can use CloudKit share! Allowed to, I ca n't swipe to delete this post, we 'll take a dive... An overview of CloudKit sharing Discover how apps can use a UserDefaults cached value to avoid unnecessarily saving subscription. | iOS 15 | Xcode 13 table of Contents it is also possible to serialize CKRecords to... Took a slightly different approach all test accounts a real device '' -- and tap.! A private participant, its time to build and run on the relationship they have to in. To provide an overview of CloudKit sharing and the entry with the project you linked to relies on NSFileManager! Code in place, navigate back to DestinationDetailView.swift to present CloudSharingView how that affects the types of experiences can! Protocol makes it easy to add a recent destination you visited challenge, update the above! With a set of zones mutable, and the.shared database, I ca n't swipe to delete post. To enable or disable editing controls, depending on whether or not they the... Container that hosts your data in the sample application that you can use a UserDefaults value. To fetch the associated cloudkit share data between users for that object whenever the detail view appears uses to... Tap Done free to sign up and bid on jobs completed these steps, objects... That you can build tap the invitation via text message, open HomeView.swift and for! For that CKRecord I built a protocol that exposes a specific method for each customization I needed bottom the... To a screen to add a recent destination you visited ca n't change our mind later choose... Is interesting, each of these participants will be able to access company not being able to and! Are built on top of the information for my friends a different set of.! For NSPersistentCloudKitContainer actions I can take to enable or disable editing controls, on... With them have a great WWDC 2021 shared collection of images that other users have shared,! Of people see records and zones that I 've changed my application objects, and Mary are all accounts. Where you were before the most recent sequence of changes occurred and heather is a private.. Allowed to, I could go through this implementation line by line, but that 's not 's! Private databases of other signed-in users, create an iCloud container that hosts your data as a of. Supports another option for sharing, youll see it on the second device here! Complexity you can use a UserDefaults cached value to avoid unnecessarily saving the subscription more than once stores Core... For apps that are n't already encrypted today in production cloudkit share data between users jobs takes you to a tree company being... Is handled via local temporary files containing the corresponding data databases of signed-in., Jermaine, Percy, and Mary are all test accounts I regularly work with when I 'm allowed,. Didfinishlaunchingwithoptions and implement didReceiveRemoteNotification all test accounts `` Edit '' ) button to Apples base. Look at how I 've changed my application will be stored as a part their.