You've been developing your app with a Core Data stack and now you want to add the cloud component. Prompt the user to login and save all its data to the cloud to make it available on all its devices. Or maybe it's a content sharing app where you need to distribute data to users of the app.

In any case, writing networking code is time consuming and error prone, so you may turn to CloudKitParse or Firebase to intergrate the cloud component. In the case of CloudKit, you can only support iOS devices and if you go with Parse or Firebase you'd have to re-write all the Core Data code.
 
The Couchbase Mobile team and community have been working really hard on a pluggable component to add sync to your app without re-writing your Core Data models and keeping the cross-platform support. On iOS, the NSIncrementalStore class provides hooks to add pluggable back-ends to your Core Data stack.

It's called CBLIncrementalStore and you can find it in the Extra folder of the .zip file downloadable here.

Make sure to include the CouchbaseLite.framework as well as this class to use it in your project:

 

 

How to use CBLIncrementalSore

The setup process is very similar to how you would set up a Core Data stack backed by an NSSQLiteStore store. So let's dive in.

The goal is to have an NSManagedObjectContext instance that is associated with a persistent store coordinator loading our managed object model. And finally add a persistent store of type CBLIncrementalStoreType to the persistent store coordinator.

 

You could create a new class called CoreDataStack to hold the set up logic:

 

Let's describe what's happening step by step:

  • Step 1: Load the model that we defined in the .xcdatamodelmodelId files.
  • Step 2: Call updateManagedObjectModel: to insure the Core Data model is mapped to a model Couchbase Lite understands.
  • Step 3: Initialize the persistent store coordinator as usual
  • Step 4: Set up the managed object context
  • Step 5: Check if the corresponding Couchbase Lite database exists. If so, we load the existing CBLDatabase as a CBLIncrementalStore store type. If not, we perform a migration from the previous SQLite data store to Couchbase Lite.

 

Adding sync

The CBLIncrementalStore class has a database property, you can create replication as usual with Couchbase Lite and Sync Gateway:

You can also add authentication with the CBLAuthenticator class. See the documentation on replications to see how to do this.

 

Core Data entities in JSON

Whenever a new entity is saved in Core Data, CBLIncrementalStore adds a CBLIS_type key in the corresponding JSON document stored in Couchbase Lite.

 

From the point of Couchbase Lite and Sync Gateway, it's JSON as usual and nothing different there. But having this mapping in mind is useful because you can also use the REST API to add new documents or display them on a web page.

curl -X POST -H 'Content-Type: application/json'        -d '{"CBLIS_type": "Person", "name": "Johnny"}'          http://localhost:4984/testdb/

 

For the more curious: subclassing NSIncrementalStore

To understand how CBLIncrementalStore works, we must follow the api spec: “NSIncrementalStore subclasses must register
their class with NSPersistentStoreCoordinator, which then constructs persistent store instances as necessary when –
addPersistentStoreWithType:configuration:URL:options:error: is called.” (read more on nshipster)

Once we register our new store, a couple of method will be called on CBLIncrementalStore, namely:

+type and +initialize

The initialize class method is called the first time the class is loaded. That's where CBLIncrementalStore registers
itself with the NSPersistentStoreCoordinator. So when we call addPersistentStoreWithType:configuration:URL:options:error: with the CBLIncrementalStore type, it will know about this new store type.

-loadMetada

Called automatically by the NSPersistentStoreCoordinator. It will create a Couchbase Lite database, initialize the views to query documents by type and for
to-many relationships and sets up the metadata for the store. This method also creates a live query for conflicting
documents.

-executeRequest:withContext:error:

This method is called to do all read and write operations with a persistence
backend. 

If the requestType is NSSaveRequestType, CBLIncrementalStore will map appropriately the Core Data
NSManagedObject to the Couchbase Lite document if it's a new entity created, an update or deletion of objects. 

If the requestType is NSFetchRequestType, CBLIncrementalStore will query the documents and return an array of
objects according to a fetch entity name & predicate.

This conforms to how subclasses of NSIncrementalStore should initialize themselves. You can read more about
NSIncrementalStore on nshipster.

Author

Posted by James Nocentini, Technical Writer, Mobile, Couchbase

James Nocentini is the Technical Writer in charge of the documentation for Couchbase Mobile. Previously, he worked as a Developer Advocate and before that as a front-end developer for HouseTrip. He also enjoys writing Android tutorials for raywenderlich.com in his spare time.

2 Comments

  1. Awesome! A demo app demonstrating exactly how this works would be pretty cool. The problem still lies — if you want to fetch data directly from the server, you have to do it through other means!

    1. James Nocentini March 16, 2015 at 9:33 am

      If you need to fetch data from the server you can use the REST API for that. Search results are a good example where you need to fetch the documents directly from the server. You can define a view in the couchbase server web console, then query this view via sync gateway and display the results on the device. When the user favourites/bookmarks an item it can then be synched to the user account via the sync function.

Leave a reply