Как получить данные с помощью предиката со строкой формата ALL ... IN - PullRequest
0 голосов
/ 14 июля 2020

Итак, у меня есть основная сущность «транзакция» с атрибутом «теги», который связан с «тегом» другой сущности. Типы отношений между двумя объектами - многие ко многим. Это означает, что у транзакции может быть много тегов, а у тега может быть много транзакций.

Теперь я создал метод, который будет извлекать записи транзакций на основе определенных тегов c. Метод выглядит примерно так:

func transactions(withTags tags: [Tag] = [], matchCriteria: String = "ANY") {...}

Итак, в функции я использовал предикат, подобный приведенному ниже:

predicate = NSPredicate(format: "(%@ <= date) AND (date < %@) AND (\(matchCriteria) tags IN %@)", argumentArray: [startDate, endDate, tags])

Таким образом, ключевым элементом в предикате является «ЛЮБОЙ теги IN% @ ", который просто выполняет поиск заданного тега (ов), и если какой-либо из этих тегов будет найден в записи, то будет найдено совпадение. Этот предикат отлично подходит для этой цели.

Но теперь я хочу иметь аналогичный предикат, но я бы хотел, чтобы он возвращал совпадение только тогда, когда будут найдены ВСЕ заданные теги. Например, если у меня есть 2 тега, например, «запланировано» и «оплачено». Тогда должны быть возвращены только записи с обоими тегами.

Итак, исходя из документации Apple здесь https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html# // apple_ref / doc / uid / TP40001795 , похоже, что есть «ВСЕ» оператор. Итак, я попытался создать предикат, подобный приведенному ниже:

predicate = NSPredicate(format: "(%@ <= date) AND (date < %@) AND (ALL tags IN %@)", argumentArray: [startDate, endDate, tags])

Просто заменил ANY на ALL. Но похоже, что это не работает, и мое приложение вылетает. Я получаю сообщение об ошибке «Поток 1: Исключение:« Неподдерживаемый предикат ... ». Здесь я застрял и надеюсь, что вы, ребята, сможете указать мне правильное направление.

Что должно быть правильным Предикат быть для меня, чтобы удовлетворить вышеуказанные требования?

Заранее спасибо!

1 Ответ

0 голосов
/ 14 июля 2020

Сначала просто обратите внимание, что, даже если бы он не взломал sh, ваш предикат («ВСЕ теги в% @», теги) не будет делать то, что вы хотите. Это обеспечит включение транзакции в результаты только в том случае, если все ее теги находятся в списке. Но если бы у него был только один тег, соответствующий только одному из вашего списка, он все равно был бы включен. Вам нужно обратное («ВСЕ теги% @ IN»). Но это вызовет ту же ошибку sh.

Самый простой способ добиться того, чего вы хотите, - это подготовить составной предикат, взяв каждый тег из вашего списка по очереди, например:

"(ANY tags == 'planned') AND (ANY tags == 'paid')"

Вы можете довольно быстро построить это для своего tags массива:

let datePredicateArray = [NSPredicate(format: "(%@ <= date) AND (date < %@)", argumentArray: [startDate, endDate])]
let tagPredicateArray = tags.map {NSPredicate(format:"ANY tags == %@", $0)}
let allPredicates = datePredicateArray + tagPredicateArray
let finalPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: allPredicates)
...