This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| In addition to data, CloudKit may also be used to store larger assets such as audio or video | |
| files, large documents, binary data files or images. These assets are stored within CKAsset | |
| instances. Assets can only be stored as part of a record and it is not possible to directly | |
| store an asset in a cloud database. Once created, an asset is added to a record as just | |
| another key-value field pair. The following code, for example, demonstrates the addition | |
| of an image asset to a record: | |
| let imageAsset = CKAsset(fileURL: imageURL) | |
| let myRecord = CKRecord(recordType: "Vacations") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| See: http://www.techotopia.com/index.php/An_Introduction_to_CloudKit_Data_Storage_on_iOS_8 | |
| A group of record operations may be performed in a single transaction using the | |
| CKModifyRecordsOperation class. This class also allows timeout durations to be specified for | |
| the transaction, together with completion handlers to be called at various stages during the | |
| process. The following code, for example, uses the CKModifyRecordsOperation class to add three | |
| new records and delete two existing records in a single operation. The code also establishes | |
| timeout parameters and implements all three completion handlers. Once the modify operation | |
| object has been created and configured, it is added to the database for execution: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| See: http://www.techotopia.com/index.php/An_iOS_8_CloudKit_Subscription_Example | |
| 01. Configure App for Remote Notifications | |
| Before adding any code to the project, a couple of configuration changes need to be made to the project to add support for notifications. First, the Info.plist file needs to be updated to indicate that the app supports remote notifications when in the background. To add this setting, select the Info.plist file from the project navigator panel and add a new entry for the Required background modes key. | |
| Once the key has been added, click on the right-facing arrow to the left of the key to unfold the values. In the value field for Item 0, enter remote-notification. | |
| 02. Registering an App to Receive Push Notifications |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| See: | |
| The CloudKitNote Class | |
| For starters, a few custom errors can be defined to shield the client from the internals of CloudKit, and a simple delegate protocol can inform the client of remote updates to the underlying Note data. | |
| import CloudKit | |
| enum CloudKitNoteError : Error { | |
| case noteNotFound |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| See: https://www.whatmatrix.com/blog/a-guide-to-cloudkit-how-to-sync-user-data-across-ios-devices/ | |
| CloudKit Notifications provide the means to find out when records have been updated by another client. However, network conditions and performance constraints can cause individual notifications to be dropped, or multiple notifications to intentionally coalesce into a single client notification. Since CloudKit’s notifications are built on top of the iOS notification system, you have to be on the lookout for these conditions. | |
| However, CloudKit gives you the tools you need for this. | |
| 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 what’s changed since the last time you asked. In my example, I do this by using CKFetchRecordZoneChangesOperation and CKServerChangeTokens. Change tokens can be thought of like a bookmark telling you wher |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| See: https://www.whatmatrix.com/blog/a-guide-to-cloudkit-how-to-sync-user-data-across-ios-devices/ | |
| Saving records is, perhaps, the most complicated operation. The simple act of writing a record to the database is straightforward enough, but in my example, with multiple clients, this is where you’ll face the potential issue of handling a conflict when multiple clients attempt to write to the server concurrently. Thankfully, CloudKit is explicitly designed to handle this condition. It rejects specific requests with enough error context in the response to allow each client to make a local, enlightened decision about how to resolve the conflict. | |
| Although this adds complexity to the client, it’s ultimately a far better solution than having Apple come up with one of a few server-side mechanisms for conflict resolution. | |
| 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. I |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| See: https://www.whatmatrix.com/blog/a-guide-to-cloudkit-how-to-sync-user-data-across-ios-devices/ | |
| Subscriptions are one of the most valuable CloudKit features. They build on Apple’s notification infrastructure to allow various clients to get push notifications when certain CloudKit changes occur. These can be normal push notifications familiar to iOS users (such as sound, banner, or badge), or in CloudKit, they can be a special class of notification called silent pushes. These silent pushes happen entirely without user visibility or interaction, and as a result, don’t require the user to enable push notification for your app, saving you many potential user-experience headaches as an app developer. | |
| The way to enable these silent notifications is to set the shouldSendContentAvailable property on the CKNotificationInfo instance, while leaving all of the traditional notification settings (shouldBadge, soundName, and so on) unset. | |
| Note also, I am using a CKQuerySubscription with a very simple “always true” pre |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| See: https://www.whatmatrix.com/blog/a-guide-to-cloudkit-how-to-sync-user-data-across-ios-devices/ | |
| Since this is a first example of using an operation, here are a couple of general observations: | |
| First, all CloudKit operations have custom completion closures (and many have intermediate closures, | |
| depending on the operation). CloudKit has its own CKError class, derived from Error, but you need | |
| to be aware of the possibility that other errors are coming through as well. Finally, one of the | |
| most important aspects of any operation is the qualityOfService value. Due to network latency, | |
| airplane mode, and such, CloudKit will internally handle retries and such for operations at a | |
| qualityOfService of “utility” or lower. Depending on the context, you may wish to assign a higher |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| See: https://www.whatmatrix.com/blog/a-guide-to-cloudkit-how-to-sync-user-data-across-ios-devices/ | |
| The CloudKitNoteDatabase Singleton | |
| CloudKit operations provide superior control over the details of how CloudKit does its work and, | |
| perhaps more importantly, really force the developer to think carefully about network behaviors | |
| central to everything CloudKit does. For these reasons, I am using the operations in these code | |
| examples. | |
| Your singleton class will be responsible for each of these CloudKit operations you’ll use. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| See: https://www.invasivecode.com/weblog/advanced-cloudkit-part-iii | |
| 01. Each time a change occurs, a remote push notification will be sent to the device. This notification includes the recordID of the changed record together with the database (public or private) and the reason that the push notification was trigged. There are three possible reasons that could have triggered the notification: a record has changed, a new record has been added, or an existing record has been deleted. When you create a subscription you have to specify which record type you want to track and the reason (creation, deletion or change). This is an example of how you would create a subscription in Swift: | |
| func subscribeToWordDefinitionChanges() { | |
| let predicate = NSPredicate(format: "TRUEPREDICATE") | |
| let subscription = CKSubscription(recordType: "WordDefinitions", predicate: predicate, options: [.FiresOnRecordCreation, .FiresOnRecordUpdate, .FiresOnRecordDeletion]) | |
| let publicDatabase = CKContainer.defaultContainer().publicC |