I have a class Download
that serves as a wrapper for CKQueryOperation
. One of the inits allows me to build my predicate with an array of values:
init(type: String, queryField: String, queryValues: [CKRecordValue], to rec: RecievesRecordable, from database: CKDatabase? = nil) {
let predicate = NSPredicate(format: "\(queryField) = %@", argumentArray: queryValues)
query = CKQuery(recordType: type, predicate: predicate)
reciever = rec
db = database
super.init()
}
When I test it, query
only matches the first value in the array. So if queryValues = [testValue0, testValue1]
and I have one record whose field matches testValue0
and I have a second record that matches testValue1
, only the first record will be discovered. If I switch the order, than the other record gets recognized.
It seems weird that I can create a predicate with an array but only the first value gets matched. The documentation says that values are substituted in the order they appear, but shouldn't it still be moving on to the second value?
For more context, each record is stored in a separate database (private vs public) and my Download
class launches two separate CKQueryOperations
that both rely on query
, if database
param is left nil. Whichever op fails ends up finding no results that match the first value and then giving up before checking the second value.
I can include the full code for 'Download' and my failing unit test if needed.
You are using the wrong predicate. You want to use the IN
operation. And instead of using string substitution for the field name, use the %K
format specifier:
let predicate = NSPredicate(format: "%K IN %@", arguments: queryField, queryValues)
Note that the NSPredicate(format:argumentArray:)
expects there to be one format specifier in the format string for each value in the argument array. Since your format only had one format specifier, only the first value was taken from the array. And since you used =
, the field was simply compared against that one value.