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 ofTICDSApplicationSyncManager
. - 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 ofTICDSDocumentSyncManager
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.
UseTICDSSynchronizedManagedObjectContext
in place ofNSManagedObjectContext
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.
UseTICDSSynchronizedManagedObject
in place ofNSManagedObject
for every entity you wish to synchronize—either directly in your.xcdatamodel
file, or by setting custom subclasses to inherit fromTICDSSynchronizedManagedObject
.
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.
-
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).
↩