Contents

CKSyncEngine

An object that manages the synchronization of local and remote record data.

Declaration

final class CKSyncEngine

Mentioned in

Overview

Use CKSyncEngine to handle your app’s CloudKit sync operations and benefit from the performance and reliability it provides. To use the class, create an instance early in your app’s launch process and specify a database to sync. Thereafter, and depending on good system conditions, the sync engine periodically pushes and pulls database and record zone changes on the app’s behalf. To participate in those sync operations and to provide the engine with the changes to send, create a type that conforms to CKSyncEngineDelegate and assign an instance of it to the engine’s configuration. You can have multiple instances of CKSyncEngine in a single process, each targeting a different database. For example, you may have one syncing a person’s private database and another syncing their shared database.

Because periodic sync relies on good system conditions — adequate battery charge, an active network connection, a signed-in iCloud account, and so on — the engine’s sync schedule is indeterminate. If you need to sync immediately, like when your app requires it has the most recent changes before continuing, use the fetchChanges(_:) and sendChanges(_:) methods.

The sync engine uses an opaque type to track its internal state, and it’s your responsibility to persist that state to disk and make it available across app launches so the engine can function properly. For more information, see handleEvent(_:syncEngine:) and CKSyncEngine.Event.StateUpdate.

CKSyncEngine requires the CloudKit and Remote notifications entitlements. For more information, see Configuring iCloud services and Configuring background execution modes.

Send changes to iCloud

A sync engine requires you to tell it about any changes to send, which you do by invoking the add(pendingDatabaseChanges:) and add(pendingRecordZoneChanges:) methods on the engine’s state property. If there are no scheduled sync operations when you invoke these methods, the engine automatically schedules one. Database changes don’t require any additional input, but the sync engine does expect you to provide the individual record zone changes — in batches — and return them from your delegate’s implementation of nextRecordZoneChangeBatch(_:syncEngine:). After the engine sends the changes, it notifies your delegate about their success (or failure) by dispatching CKSyncEngine.Event.sentDatabaseChanges(_:) and CKSyncEngine.Event.sentRecordZoneChanges(_:) events.

Fetch changes from iCloud

By default, a sync engine attempts to discover an existing CKDatabaseSubscription for the associated database and uses that to receive silent notifications about remote record changes. If the engine doesn’t find a subscription, it automatically creates one to use. On receipt of a notification, the engine schedules a sync operation to fetch the related changes. When that operation runs, the engine dispatches a CKSyncEngine.Event.willFetchChanges(_:) event to your delegate. As it receives fetched changes, the engine dispatches CKSyncEngine.Event.fetchedDatabaseChanges(_:) and CKSyncEngine.Event.fetchedRecordZoneChanges(_:), accordingly. After the operation finishes, the sync engine notifies your delegate by dispatching a CKSyncEngine.Event.didFetchChanges(_:) event. You handle all dispatched events in your delegate’s implementation of handleEvent(_:syncEngine:).

Sync Scheduling

Automatic sync

By default, the sync engine automatically schedules sync tasks on your behalf. If the user is signed in, the device has a network connection, and the system is generally in a good state, these scheduled syncs happen relatively quickly. However, if the device has no network, is low on power, or is otherwise under a heavy load, these automatic syncs might be delayed. Similarly, if the user isn’t signed in to an account, the sync engine won’t perform any sync tasks at all.

Manual sync

There may be some cases where you want to manually trigger a sync. For example, if you have a pull-to-refresh UI, you can call fetchChanges(_:) to tell the sync engine to fetch immediately. Or, if you have a “backup now” UI, you can call sendChanges(_:) to send to the server immediately.

Error Handling

There are some transient errors that the sync engine handles automatically behind the scenes. The sync engine retries the operations for these transient errors automatically when it makes sense to do so. Specifically, the sync engine will handle the following errors on your behalf:

When the sync engine encounters one of these errors, it waits for the system to be in a good state, and tries again. For example, if the server sends back a CKError.Code.requestRateLimited error, the sync engine respects this throttle and tries again after the error’s retry-after time.

CKSyncEngine does not handle errors that require application-specific logic. For example, if you try to save a record and get a CKError.Code.serverRecordChanged, you need to handle that error yourself. There are plenty of errors that the sync engine cannot handle on your behalf, see CKError for a list of all the possible errors.

Accounts

CKSyncEngine monitors for account status, and it only syncs if there’s an account signed in. Because of this, you can initialize your CKSyncEngine at any time, regardless of account status. If there is no account, or if the user disabled sync in settings, the sync engine stays dormant in the background. Once an account is available, the sync engine starts syncing automatically.

The sync engine listens for when the user signs in or out of their account. When it notices an account change, it sends an CKSyncEngine.Event.accountChange(_:) to your delegate. It’s your responsibility to react appropriately to this change and update your local persistence.

Topics

Creating a sync engine

Accessing the engine’s attributes

Participating in scheduled sync operations

Invoking manual sync operations

Canceling operations

Debugging the sync engine

Structures

Enumerations

Default Implementations

See Also

Records