Предикат Swift соответствует только первому значению в массиве значений

У меня есть класс Download который служит оберткой для CKQueryOperation, Один из элементов позволяет мне построить свой предикат с массивом значений:

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()
}

Когда я проверю это, query соответствует только первому значению в массиве. Так что если queryValues = [testValue0, testValue1] и у меня есть одна запись, чьи поля соответствуют testValue0 и у меня есть вторая запись, которая соответствует testValue1только первая запись будет обнаружена. Если я переключу порядок, то другая запись будет распознана.

Кажется странным, что я могу создать предикат с массивом, но сопоставляется только первое значение. В документации сказано, что значения подставляются в том порядке, в котором они появляются, но разве не следует перейти к второму значению?

Для большего контекста, каждая запись хранится в отдельной базе данных (частной и общедоступной) и мой Download класс запускает два отдельных CKQueryOperations что оба полагаются на query, если database параметр остался ноль. В зависимости от того, что произойдет, операция не найдет результатов, соответствующих первому значению, а затем сдастся, прежде чем проверять второе значение.

Я могу включить полный код для "Скачать" и мой провал модульный тест, если это необходимо.

2 ответа

Решение

Вы используете неправильный предикат. Вы хотите использовать IN операция. И вместо использования замены строки для имени поля, используйте %K спецификатор формата:

let predicate = NSPredicate(format: "%K IN %@", arguments: queryField, queryValues)

Обратите внимание, что NSPredicate(format:argumentArray:) ожидает, что в строке формата будет один спецификатор формата для каждого значения в массиве аргументов. Поскольку у вашего формата был только один спецификатор формата, из массива было взято только первое значение. И так как вы использовали =поле просто сравнивали с этим одним значением.

Основные сравнения=, == Левое выражение равно правому.

=, => Левое выражение больше или равно правому выражению. <=, =< Левое выражение меньше или равно правому выражению. Левое выражение больше правого. < Левое выражение меньше правого. !=,<> Левое выражение не равно правому выражению.

Сравнение строк

НАЧИНАЕТСЯ Левое выражение начинается с правого выражения.

CONTAINS Левое выражение содержит правое выражение.

ENDSWITH Левое выражение заканчивается правым выражением.

LIKE Левое выражение равно правому: ? а также

  • разрешены как подстановочные знаки, где ? соответствует 1 символу, а * соответствует 0 или более символам.

СОВПАДЕНИЯ Левое выражение равняется правому выражению с использованием сравнения в стиле регулярных выражений в соответствии с ICU v3 (дополнительную информацию см. в Руководстве пользователя ICU по регулярным выражениям).

Я использовал базовые сравнения

      let resultPredicate = NSPredicate(format: "%K = %@", "key", "value")
let result_filtered = MYARRAY.filtered(using: resultPredicate) as NSArray

Дополнительная информация: Руководство по программированию предикатов

Другие вопросы по тегам