CloudKit Querying

Episode #260 | 12 minutes | published on March 16, 2017 | Uses iOS-10.2, Xcode-8.2
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)
blog comments powered by Disqus