ZumeroIncrementalStore is an NSIncrementalStore subclass that lets you use Core Data with the Zumero SDK to sync data between iOS and Mac apps. Zumero is a "replicate and sync" technology based on SQLite that allows apps to be fully functional offline and sync in the background when they're online.
It means that you can add syncing to your Core Data app by swapping out Apple's NSPersistentStore with ZumeroIncrementalStore, and as far as the app knows, it's just using Core Data with a local data file. Then whenever you want your app to sync, you call a sync method in the Zumero iOS SDK, and sync happens in the background.
Here's a top-level overview of how it works:
The next figure shows how ZumeroIncrementalStore fits into the Core Data stack:
You can find a blog post at grasmeyer.com that shows a comparison of the most popular syncing technologies.
- You don't have to make any changes to your Core Data model, like adding extra attributes to your entities or subclassing a custom model object base class.
- You can sync data between multiple users.
- You can sync data with non-Apple platforms such as web apps and Android apps.
- It supports versioning and migrations.
- Each user's data is isolated in their own data file, so they can migrate to the latest version independently of other users, and they can backup and restore their data independently of other users.
Normally, when you initialize the Core Data stack for an app, you add a persistent store to your persistent store coordinator with the following line of code:
[_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&error];To use ZumeroIncrementalStore instead, just replace that line of code with the following line:
[_persistentStoreCoordinator addPersistentStoreWithType:[ZumeroExampleIncrementalStore type]
configuration:nil
URL:nil
options:options
error:&error];In this case, ZumeroExampleIncrementalStore is the name of your custom subclass of ZumeroIncrementalStore.
Now you can just use Core Data as you normally would. Then when you want your app to sync, just call the following method:
[incrementalStore syncWithCompletionBlock:completionBlock]In this case, incrementalStore is the instance of ZumeroExampleIncrementalStore and completionBlock is a completion block that you can define. You will typically use this completion block to send an NSNotification to your user interface so that it can be updated with new data from the sync.
That's all there is to it!
ZumeroIncrementalStore is currently an alpha release, and it hasn't been used in any production apps yet. Feedback and contributions from the community are welcome.
ZumeroIncrementalStore requires Xcode 5, iOS 7, and Mac OS X 10.9.
Take a look at the Zumero iOS Example in the Examples directory. The example app uses several different types of entities, attributes, and relationships to demonstrate and test various aspects of ZumeroIncrementalStore.
-
Create a new project in Xcode. Don't check the Core Data checkbox.
-
Add the following line to your
Prefix.pchfile:#import <CoreData/CoreData.h> -
Drag the ZumeroIncrementalStore folder into your Xcode project. This folder should contain
ZumeroIncrementalStore.handZumeroIncrementalStore.m. Or you can use CocoaPods, as described below. -
Drag
Zumero.frameworkinto the Frameworks folder -
Click on the Target in the sidebar on the left. Click the General Tab. Add the following frameworks:
CFNetwork.framework libsqlite3.dylib libz.dylib -
Add a property to your
AppDelegate.hfile for the modelController:@property (nonatomic) ModelController *modelController; -
Initialize the
modelControllerin theapplication:didFinishLaunchingWithOptions:method of yourAppDelegate.mfile:self.modelController = [[ModelController alloc] init]; -
Set up a free account at zumero.com.
-
Create your own custom subclass of ZumeroIncrementalStore. See the section below for details.
-
Set up your Access Control List. See the section below for details.
You can also use CocoaPods to install ZumeroIncrementalStore.
platform :ios, '7.0'
pod "ZumeroIncrementalStore", "~> 0.1.0"If you want to use mogenerator, set up a Run Script via the following steps.
- Select the Target in the sidebar on the left.
- Select the Build Phases tab.
- Choose "Add Build Phase"->"Add Run Script Build Phase" from the Editor menu.
- Drag the Run Script to the second position in the list, just below Target Dependencies.
- Paste the following script into the black text field. Then you can change the values for the variables in the script.
MODEL_DIR="$PROJECT_DIR/../Common/Classes/Model"
DATA_MODEL_FILE="$MODEL_DIR/ZumeroExample.xcdatamodeld/ZumeroExample.xcdatamodel"
MACHINE_SOURCE_DIR="$MODEL_DIR/MachineClasses"
HUMAN_SOURCE_DIR="$MODEL_DIR/HumanClasses"
AGGREGATE_HEADER="$MACHINE_SOURCE_DIR/Model.h"
BASE_CLASS="ModelObject"
TEMPLATES_DIR="$PROJECT_DIR/../../mogenerator/Templates"
../../mogenerator/mogenerator --template-var arc=true --includeh "$AGGREGATE_HEADER" --template-path "$TEMPLATES_DIR" --base-class "$BASE_CLASS" -m "$DATA_MODEL_FILE" -M "$MACHINE_SOURCE_DIR" -H "$HUMAN_SOURCE_DIR"Note that ZumeroIncrementalStore doesn't require you to use a base class for your model objects. However, a base class is often useful for adding methods that apply to all of your model objects, so we used it in the example app to show how it's done.
If you don't already have mogenerator installed, you can get it here: https://github.com/rentzsch/mogenerator
After you download mogenerator, open mogenerator.xcodeproj, compile it, and drag the mogenerator executable file to ~/bin. Then you can use the absolute path to ~/bin/mogenerator in your Run Script instead of the relative path shown above.
You should create a new custom subclass of ZumeroIncrementalStore that overrides some of the methods for the server name, username and password, filenames, etc.
Here's an example of the ZumeroExampleIncrementalStore.m file from the Zumero iOS Example in the Examples directory:
#import "ZumeroExampleIncrementalStore.h"
@implementation ZumeroExampleIncrementalStore
+ (void)initialize
{
[NSPersistentStoreCoordinator registerStoreClass:self forStoreType:[self type]];
}
+ (NSString *)type
{
return NSStringFromClass(self);
}
+ (NSManagedObjectModel *)model
{
return [[NSManagedObjectModel alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"ZumeroExample" withExtension:@"momd"]];
}
+ (NSString *)databaseFilename
{
return @"zedata";
}
+ (NSString *)databaseRemoteFilename
{
return @"zeremotedata";
}
+ (NSString *)server
{
// Zumero server
// You will receive a custom Zumero Server URL when you sign up for your free Zumero account
// return @"YOUR_ZUMERO_SERVER_URL";
// Local server without virtual host
return @"http://localhost:8080";
// Get this app to use the following 2 local server URLs:
// http://clickontyler.com/virtualhostx/
// Local server with virtual host
// You can set this up in VirtualHostX
// return @"http://zumero.dev:8080";
// Local server with virtual host over local network
// You can get this URL from the "Local Domain Name" field in the Advanced Options section of the VirtualHostX window
// return @"http://zumero.dev.10.0.1.8.xip.io:8080";
}
+ (NSString *)username
{
return @"user";
}
+ (NSString *)password
{
return @"userpass";
}
+ (NSDictionary *)scheme
{
return @{ @"dbfile": @"ztauth", @"scheme_type": @"internal" };
}
@end- Download the Zumero Development Server after signing up for a Zumero account at http://zumero.com/dev-center/.
- Open a new Terminal window and cd to the
zumero_dev_serverdirectory. - Launch the local server by typing
bin/zumero. - Open a new terminal window and cd to the
Examples/Access Control List Setupdirectory in this repository. - Open the
local_setup.sqlfile and change YOUR_PASSWORD to your own password. - Initialize the local Access Control List by typing
sqlite3 :memory: -init local_setup.sql.
- The Zumero iOS SDK has a bug related to CFNetworking that can cause the sync to hang in iOS 7. Zumero is currently working with Apple to resolve this issue.
- As a result, the
SYNC_ENABLEDflag has been set to NO at the top ofAppDelegate.mfor now. - The Zumero Mac SDK framework hasn't been released yet, so the Zumero Mac Example is just a placeholder for now.
- There is a bug in Xcode 5 that causes the labels to be hidden in some of the UITableViewCells within the Storyboard.
- Add more unit tests
- Add progressive migration as explained in Marcus Zarra's excellent Core Data book
- Add more documentation
- Add support for external blobs
Unfortunately, NSIncrementalStore isn't very well documented. Here are some references if you want to get more info about it.
Apple's Incremental Store Programming Guide:
Here are a few good blog posts about NSIncrementalStore:
- http://sealedabstract.com/code/nsincrementalstore-the-future-of-web-services-in-ios-mac-os-x/
- http://nshipster.com/nsincrementalstore/
- http://chris.eidhof.nl/post/17826914256/accessing-an-api-using-coredatas-nsincrementalstore
Here are some examples of how others are using NSIncrementalStore:
- https://github.com/AFNetworking/AFIncrementalStore
- https://github.com/project-imas/encrypted-core-data
- http://stackmob.github.io/stackmob-ios-sdk/Classes/SMIncrementalStore.html
- http://www.stoeger-it.de/en/secureincrementalstore/
- https://github.com/chbeer/CBCouchbaseIncrementalStore
- https://groups.google.com/forum/#!topic/mobile-couchbase/3BQHsGz_2A0
ZumeroIncrementalStore is available under the MIT license. See the LICENSE.txt file for more info.

