WWDC 2015

CloudKit Tips and Tricks

Swiftification

Subscript

record.setObject(5, forKey:"num")
var aDate = record.objectForKey("date") as! NSDate

change into

record["num"] = 5
var aDate = record["date"]

Light generic

// [String] can not be assigned to [CKReocrd]?
modifyRecordsOperation.recordsToSave = ["I'm not a CKRecord!"]

Account Status

//check the current account status 
container.accountStatusWithCompletionHandler { accountStatus, error in 
...
}

Retrying Operations

CKErrorNetworkFailure

for poor network conditions

Busy Servers

CKErrorServiceUnavailable

and

CKErrorZoneBusy

look for CKErrorRetryAfterKey for time needed for retrying

Rate Limiting

CKErrorRequestRateLimited error is emitted when the quote is hit.

Handling Conflicts

CKErrorServerRecordChanged
``` for the error of conflicting records

retrieve all updated records via ```[CKRecordChangedErrorServerRecordKey``` and append newly created to the end

Suggested way for 1 to m relationships

![](clockKitOneToM.PNG)

## Batch Operation

use ```CKModifyRecordsOperation(recordsToSave: [CKRecord]?, recordIDsToDelete[CKRecordID]?)``` to submitting multiple records at once and reduces fixed overheads. 

```CKErrorPartialFailure``` is raised if some of the records operation are not successful.

## Query

**result size limit**

// get 20 results let queryOperation= CKQueryOperation.. queryOperation.resultsLimit = 20


**dedicated keys**

let queryOperation = CKQueryOperation queryOperation.desiredKeys = ["photoThumbnail"]


**sorting**

let queryOperation = NSSortDescriptor(key : "creationDate", ascending: false) query.sortDescriptors = [byCreation]


Config field sorting via iCloud Dashboard before the records created.


**Pagination**

set ```queryCompletionBlock``` and retrieve ```CKQueryCursor``` for reminding results

## Local cache

using private database for personal data

``` let customZone = CKReocrdZone(zoneName: "custom")
  • use CKQueryOperation to query
  • Delta downloads using CKFetchRecordChangesOperation
    • Custom zone with CKRecordZoneCapabilityFetchChanges

invoke record.encodeSystemFieldsWithCoder and record.decodeSystemFieldsWithCoder to archive CKRecord and avoid conflicts

only need to provide the fields need to change and accompanying with CKRecord

Subscriptions

  • notify app of any changes on

    • Query that satisfy
    • zone
  • User Notification

    • enable APS
    • entitlement
    • Registration with UIApplication
  • Silent Push

    • REmote notification background mode
    • handle via func application(application: UIApplication, didReceiveREmoteNotification: [NSObject: AnyObject], fetchCompletionHandler: (UIBackgroundFetchResult) -> Void) { }
    • setting CKNotificationInfo.shouldSendContentAvailable = true with no alert body, should barge and soundName

retrieve collection of push with CKFetchNotificationChangesOperation and handle background task with UIApplication.beginBackgroundTaskWithName

  • Interactive Notificaion
    • set CKNotificationInfo.category

Performance

use NSOperation dependency to manage tasks relationships for sake of readability and ease for debug

set QoS for NSOperation for let system to handle the operation and perform the tasks