Search code examples
iosswiftcloudkit

Code pattern / snippet for retrieving single column from cloudkit


I'm building an app which allows users to upload / download info from a common store. I thought cloudKit storage would be ideal for this.

I'd like for users to be able to search records in the store by a KeyWord field, then download the entire record when they select one.

In SQL terms this would be like:

SELECT id,KeyWords from myDB WHERE KeyWords LIKE %searchstring%

Followed by:

SELECT * FROM myDB WHERE id = selectedID

I have been using this code pattern to retrieve records from cloudKit storage:

var publicDatabase: CKDatabase?
let container = CKContainer.defaultContainer()

override func viewDidLoad() {
    super.viewDidLoad()
    publicDatabase = container.publicCloudDatabase
}

func performQuery(){
    let predicate = NSPredicate(value: true)
    let query = CKQuery(recordType: "Library", predicate: predicate)
    publicDatabase?.performQuery(query, inZoneWithID: nil,
        completionHandler: ({results, error in

        ...
        [code to handle results / error here]
        ...
    })
}

but this returns all the content of each record which is a lot of unnecessary info.

I'd like to only fetch a single field from the cloudkit records.

Is there an easy way to do this and does anyone have a code snippet?

CKFetchRecordsOperation allows downloading of restricted columns but requires that you know the ids of the records to download.


Solution

  • OK Got something working. This may well be hacky but I put it up for info for anyone else in the same situation...

    let predicate = NSPredicate(value: true) // returns all - replace with whatever condition you want
    let query = CKQuery(recordType: "Library", predicate: predicate) // create a query using the predicate
    var operation = CKQueryOperation(query: query) // create an operation using the query
    operation.desiredKeys = ["KeyWords"] // Array of whatever 'columns' you want to return
    // operation.resultsLimit = 15 // optional limit on records
    
    // Define a closure for what to do for each returned record
    operation.recordFetchedBlock = { [weak self] (record:CKRecord!) in
    
        // Do whatever you want with each returned record  
        println(record.objectForKey("KeyWords"))
    
    }
    
    // Define a closure for when the operation is complete
    operation.queryCompletionBlock = { [weak self] (cursor:CKQueryCursor!, error:NSError!) in
    
            if cursor != nil {
                // returns the point where the operation left off if you want t retrieve the rest of the records
            }
    
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
    
                // Do what you want when process complete
                self!.tableView.reloadData()
                if error != nil {
                    println("there was an error")
                }
            })
        }
    
    self.publicDatabase!.addOperation(operation) // Perform the operation on given database