NachoMan / CKSIncrementalStore

CoreData Store with Sync for CloudKit

Home Page:https://medium.com/@NofelMahmood/reason-why-cloudkit-cannot-be-ignored-9c7806d76230

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

#CKSIncrementalStore

CKSIncrementalStore is a subclass of NSIncrementalStore. It automatically creates and manages a SQLite store using CoreData to store and sync with user's private database on CloudKit Servers.

It helps you to reuse your CoreData knowledge to power your apps with CloudKit. It handles almost all the CloudKit hassle.

####Seeing is believing !

Start by Adding it

var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel:self.managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("CKSIncrementalStore_iOSDemo.sqlite")
var error: NSError? = nil
var failureReason = "There was an error creating or loading the application's saved data."
  
var persistentStore:NSPersistentStore? = coordinator!.addPersistentStoreWithType(CKSIncrementalStore.type, configuration: nil, URL: url, options: nil, error: &error)

if persistentStore != nil
{
    self.cksIncrementalStore = persistentStore as? CKSIncrementalStore
    // Store it in a property.
}

How Sync Works

Sync operation uses a private instance of NSManagedObjectContext to perform the operation and throws two notifications to notify when the operation starts and finishes.

Notifications
  • CKSIncrementalStoreDidStartSyncOperationNotification

Notification is posted when the sync operation starts.

Example

NSNotificationCenter.defaultCenter().addObserver(self, selector: "syncFinished:", name: CKSIncrementalStoreDidStartSyncOperationNotification, object: self.cksIncrementalStore)
  • CKSIncrementalStoreDidFinishSyncOperationNotification

Notification is posted when the sync operation finishes.

Example

NSNotificationCenter.defaultCenter().addObserver(self, selector: "syncFinished:", name: CKSIncrementalStoreDidFinishSyncOperationNotification, object: self.cksIncrementalStore)

Sync works in two ways. One is manual and the other is automatic.

Ways to Sync
  • Manual Sync

Anytime call triggerSync() on an instance of CKSIncrementalStore.

self.cksIncrementalStore.triggerSync()
  • Automatic Sync

Well anytime you call save on an instance of NSManagedObjectContext, CKSIncrementalStore calls triggerSync() automatically.

But what if some other device changes some records on the server. Don't worry we have you covered but we need some of your help too.

Enable Push Notifications for your app. Then in your AppDelegate's method

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) 
{
    self.cksIncrementalStore?.handlePush(userInfo: userInfo)
}

Sync Conflict Resolution

Life is usually filled up with conflicts and so is data. The good thing about "data" is that we can easily resolve conflicts using libraries like this one.

CKSIncrementalStore supports 4 sync conflict resolution policies out of the box.

  • GreaterModifiedDateWins

This is the default. Record with the greater modified date is considered to be the true record.

  • UserTellsWhichWins

Setting this sync policy requires that you set the recordConflictResolutionBlock instance of CKSIncrementalStore.

var recordConflictResolutionBlock:((clientRecord:CKRecord,serverRecord:CKRecord)->CKRecord)?

It gives you two versions of the record. Client record and Server record. You do what ever changes you want on the server record and return it.

  • ServerRecordWins

It simply considers the Server record as the true record.

  • ClientRecordWins

It simply considers the Client record as the true record.

You can set any policy by passing it as an option while adding CKSIncrementalStore to NSPersistentStoreCoordinator.

var options:Dictionary<NSObject,AnyObject> = Dictionary<NSObject,AnyObject>()
options[CKSIncrementalStoreSyncConflictPolicyOption] = NSNumber(short: CKSStoresSyncConflictPolicy.ClientRecordWins.rawValue)
var persistentStore:NSPersistentStore? = coordinator!.addPersistentStoreWithType(CKSIncrementalStore.type, configuration: nil, URL: url, options: options, error: &error)

What it does support

CKSIncrementalStore supports only user's CloudKit Private Database at this time. It creates and uses a custom zone to store data and fetch changes from the server.

What it does not support

CloudKit Public Database and here's the two reasons why, straight from the docs.

  1. The disadvantage of using the default zone for storing records is that it does not have any special capabilities. You cannot save a group of records to iCloud atomically in the default zone. Similarly, you cannot use a CKFetchRecordChangesOperation object on records in the default zone.

  2. You cannot create custom zones in a public database.

Getting Started

See the sample iOS demo app. Run it on two devices and start adding, removing and modifying records and experience the magic.

Installation

CocoaPods is the recommended way of adding CKSIncrementalStore to your project.

You want to to add pod 'CKSIncrementalStore', '~> 0.5.2' similar to the following to your Podfile:

target 'MyApp' do
  pod 'CKSIncrementalStore', '~> 0.5.2'
end

Then run a [sudo] pod install inside your terminal, or from CocoaPods.app.

Credits

CKSIncrementalStore was created by Nofel Mahmood

Contact

Follow Nofel Mahmood on Twitter and GitHub or email him at nofelmehmood@gmail.com

License

CKSIncrementalStore is available under the MIT license. See the LICENSE file for more info.

About

CoreData Store with Sync for CloudKit

https://medium.com/@NofelMahmood/reason-why-cloudkit-cannot-be-ignored-9c7806d76230

License:MIT License


Languages

Language:Swift 99.0%Language:Ruby 1.0%