Episode #260

CloudKit Querying

Series: Hello CloudKit

12 minutes
Published on March 16, 2017

This video is only available to subscribers. Get access to this video and 497 others.

Now that we have saved records in CloudKit, how do we fetch them again? This video covers how to fetch a single record by ID, how to use full-text search to match partial terms, how to return all records (with paging support) and how to query by location.

Episode Links

Query for a single record by ID


        let recordID = CKRecordID(recordName: "my-restaurant")
        container.publicCloudDatabase.fetch(withRecordID: recordID) { (record, error) in
            if let r = record {
                print("restaurant: \(r["name"])")
            }

            if let e = error {
                print("ERROR: \(e)")
            }
        }

Query for all records

For this we need to use an NSPredicate, but we really just want this to match everything...

     let predicate = NSPredicate(value: true)  // TRUE Predicate.. returns all records
     let query = CKQuery(recordType: "Restaurant", predicate: predicate)
     let queryOperation = CKQueryOperation(query: query)
     queryOperation.resultsLimit = 10

     var results: [String] = []
     queryOperation.recordFetchedBlock = { record in
         results.append(record["name"] as! String)
     }

     queryOperation.queryCompletionBlock = { cursor, error in
         if let e = error {
             print("Error executing query: \(e)")
         } else {
             print("Done!  Results: \(results)")
         }
     }   

Full-Text Search

Here we use a special allTokens field that contains tokenized words from the indexed string fields in our record. Note the modifiers we use here: [cdl]. This refers to case insensitivity, diacritic insensitivity, and locale sensitivity. The latter is required or the query will fail.

    let predicate = NSPredicate(format: "allTokens TOKENMATCHES[cdl] %@", "grill")

Query by Location

Here we specify a starting location and a radius to use for our search. To use these in a predicate, we have to call a function, which is a bit awkward within a predicate.

    let location = CLLocation(latitude: 29.8213159, longitude: -95.4244451)
    let radiusInMeters: CGFloat = 4000
    let predicate = NSPredicate(format: "distanceToLocation:fromLocation:(location, %@) < %f", location, radiusInMeters)

This episode uses Ios 10.2, Xcode 8.2.