Programming Guide

CloudKit Operation

CloudKit is a framework which enables communication between Apple's CloudKit server and user's devices. It is highly asynchronous and error prone problem domain and the CloudKit engineers have chosen to base all of the functionality on NSOperation subclasses.

CloudKitOperation is a composing operation similar to ComposedOperation. It's usage is to support executing CKDatabaseOperation subclasses. The Operation subclass supports setting the CKDatabase and executing the operation.

let fetch = CloudKitOperation(
    operation: CKFetchRecordsOperation(recordIDs: ids), 
    database: db
)
fetch.addObserver(NetworkObserver())
queue.addOperation(fetch)

Most of the CKDatabaseOperation have block based APIs which perform work during execution. These are well suited to collect input data such as records, or identifiers, and then trigger new Operation subclasses. For example creating a CloudKit zone:

// Assume we have an operation which persists some state
let didCreateZoneOperation = DidCreateCloudKitZoneOperation(zone: recordZone)

// Create the zone operation
let createZoneOperation = CloudKitOperation(
    // This is the CKDatabaseOperation we want to execute
    operation: CKModifyRecordZonesOperation(recordZonesToSave: [recordZone], recordZoneIDsToDelete: nil), 
    database: db)

// Always give our operation's names
createZoneOperation.name = "Create CloudKit Zone"

// Set the CloudKit completion block on the composed operation
createZoneOperation.operation.modifyRecordZonesCompletionBlock = { [weak operation = createZoneOperation] (saved, _, error) in
    if let error = error {
        // Handle errors..
    }
    else {
        // If there are no errors, produce the did create zone
        // operation.
        operation?.produceOperation(didCreateZoneOperation)
    }
}

👍

Making a dedicated GroupOperation subclass

The above sample code would be ideally suited to be inside a GroupOperation subclass. The intention being to encapsulate the creation of the zone, persistence of state etc.

👍

Create an OperationCondition

Going even further, such a GroupOperation would be ideal as the dependency operation for a condition. Such a condition can then be attached to other Operation subclasses which interact with the zone.