Framework Overview

Primary classes and requirements of the TICoreDataSync framework

TICoreDataSync adds synchronization capabilities to Core Data applications by tracking changes made to synchronized managed objects. These changes are pushed out to other clients during the sync process, and conflicts are handled on a “rolling sync” basis.

Primary Classes

If you are using one of the built-in synchronization types, most of the work you’ll need to do to integrate TICoreDataSync will be in creating, registering, and responding to the Sync Managers.

Sync Managers

There are two types of sync manager:

Application Sync Manager
Responsible for registering your application for a specific type of sync, fetching a list of available documents that have already been synchronized by other clients, and downloading those documents.
You usually have only one in your application, an instance of one of the sync-specific subclasses of TICDSApplicationSyncManager.
Document Sync Manager
Responsible for everything related to a single document, including registering the document for sync, uploading and downloading a copy of the entire store file, as well as the actual synchronization process.
You’ll need one for each synchronized document, allocationg one of the sync-specific subclasses of TICDSDocumentSyncManager

If you’re working with a non-document-based application, just treat the data as a single document (see the Mac Tutorial for a specific example).

Most of the individual sync manager tasks are carried out internally by operations. You don’t need to worry about these operations unless you wish to create your own set of classes to implement an unsupported type of sync.

Both sync managers make use of a large number of delegate callbacks to alert you of progress, ask for input, or allow you to customize behavior. The available callbacks (some are required) are described by the TICDSApplicationSyncManagerDelegate and TICDSDocumentSyncManagerDelegate protocols.

Managed Objects and Contexts

You will need to make use of two sync-specific Core Data subclasses:

Synchronized Managed Object Context
Keeps track of the relevant Document Sync Manager, and alerts it when the synchronized context is saved. Every change that you wish to synchronize will need to take place in a synchronized managed object context.
Use TICDSSynchronizedManagedObjectContext in place of NSManagedObjectContext when you build your Core Data stack.
Synchronized Managed Object
Recognizes when changes have been made, and creates the necessary sync change objects to describe them.
Use TICDSSynchronizedManagedObject in place of NSManagedObject for every entity you wish to synchronize—either directly in your .xcdatamodel file, or by setting custom subclasses to inherit from TICDSSynchronizedManagedObject.

You’ll also need to add a persistent string attribute called ticdsSyncID to every entity in your data model that you wish to synchronize. The framework uses this to track each object uniquely across multiple clients and sync sessions.

How Synchronization Works

Although the framework supports uploading and downloading a copy of the entire Core Data persistent store file, the primary synchronization behavior involves working with Sync Changes.

Sync Changes

When changes are made to managed objects and saved in a synchronized managed object context, TICDSSyncChange objects are created to describe each type of change:

Insertion
Managed objects have been inserted into the context.
Attributes
Persistent attributes have been modified.
Relationships
Persistent relationships have been modified.1
Deletion
Managed objects have been removed from the context.

These sync changes are kept locally in a dedicated file, stored inside a helper directory for the application (you can customize the location through delegate callbacks).

The Synchronization Process

When it comes time to synchronize, the following takes place:

Download
Any sync changes that have been posted by other clients are downloaded from the remote.
Apply
The changes are applied locally in a background managed object context, which is tied to the same local persistent store as the primary document.
Fix Conflicts
If conflicts are found with the local sync changes, these are either fixed automatically, or by asking the user/application for input via delegate callbacks.
Upload
Once all conflicts have been fixed, the local set of sync changes are uploaded to the remote.

Note that the framework never accesses files directly on the remote. Existing files are always downloaded first, new files are always created locally before being uploaded.

This behavior makes it easy to use different sync mechanisms. The framework includes generic operations that handle everything that happens locally; sync-specific subclasses simply override the methods relating to moving files between local and remote.

Encryption

TICoreDataSync supports optional encryption. If enabled, each of the following files will be encrypted when stored on the remote:

WholeStore
A copy of the entire document store file.
SyncChanges
Each set of changes made to managed objects.
deviceInfo.plist
Information about a registered client.
documentInfo.plist
Information about a synchronized document.

The framework handles encryption and decryption automatically, and is currently application-wide.

This means that you’ll need to specify whether or not to enable encryption when the application is first registered with the remote from any device. When additional devices register for the first time, each one will need to provide the password before it can access any of the synchronized documents.

All you need to do is implement two delegate methods: one to specify whether encryption should be enabled, and one to provide a password from the user the first time it is needed. Once specified, this password is stored in the keychain and accessed automatically by the framework.


  1. Sync change objects are only created for one side of the relationship: either the to-one side of a one-to-many relationship, or the alphabetically-lower-named side of a one-to-one or many-to-many relationship. In the case of identically-named relationships, the framework will currently create sync changes for both sides. This shouldn’t be a problem, but will mean that the relationships will be set twice for any client applying the changes. The framework should also cope if you use one-way relationships (no inverse).

Documentation

Reference

Source Code

Available on GitHub

Contact