Основные данные, NSPredicate и ключ ко многим

У меня есть модель Core Data, в которой объект Task включает необязательную связь со многими excludedOccurrences. Одним из свойств excludedOccurrences является start, который является объектом NSDate. Сущность ExcludedOccurrence имеет обратную связь обязательного к одному с сущностью Task.

Чтобы получить задачи на указанный день, мне нужно убедиться, что указанный день не отображается в качестве начального свойства какой-либо сущности ExcludedOccurrence. Поэтому один из под-предикатов, который я пытаюсь использовать, это

NSPredicate *occurrenceIsNotExcludedPredicate = [NSPredicate predicateWithFormat: @"(ALL excludedOccurrences.start != %@))", today];

где today - объект NSDate на сегодняшний день, включающий только компоненты дня, месяца и года. Все начальные свойства исключенных вхождений также включают только компоненты дня, месяца и года.

Хотя это должно быть нормально, по крайней мере, читая документацию по Core Data и NSPredicate, я получаю следующее сообщение об ошибке:

Завершение работы приложения из-за неперехваченного исключения «NSInvalidArgumentException», причина: «Неподдерживаемый предикат.

Если я использую эквивалентный предикат

NSPredicate *occurrenceIsNotExcludedPredicate = [NSPredicate predicateWithFormat: @"!(ANY excludedOccurrences.start == %@))", today];

исключение не генерируется, однако код работает не так, как ожидалось: вместо этого исключается возникновение на сегодня, которое не следует исключать.

Я также не уверен, как проверить случай excludedOccurrences == nil: следующий предикат

NSPredicate *nilPredicate = [NSPredicate predicateWithFormat: @"(excludedOccurrences == nil)"];

вызывает во время выполнения исключение

ключ ко многим здесь запрещен

Однако, поскольку отношение excludedOccurrences является необязательным, мне также нужно проверить, равно ли оно нулю.

Как мне с этим справиться? Заранее спасибо.


person Massimo Cafaro    schedule 22.07.2009    source источник


Ответы (4)


Чтобы проверить наличие пустого отношения, вы должны сравнить счетчик ключа ко многим с нулем.

[NSPredicate predicateWithFormat:@"excludedOccurrences.@count == 0"];

Что касается ваших субпредикатов, имейте в виду, что у вас может быть только один из модификаторов ALL или ANY в вашем последнем предикате, хотя вы можете использовать этот модификатор несколько раз во всем предикате.

Неправильно: ANY foo.bar = 1 AND ALL foo.baz = 2
Нормально: ANY foo.bar = 1 AND !(ANY foo.baz != 2)

person Ashley Clark    schedule 28.07.2009
comment
твое пустое решение для отношений рушится для меня. - person Simon Woodside; 11.01.2010
comment
К сожалению, формат предиката исправлен. Я никогда не удосужился проверить свое предположение, когда это было опубликовано, по-видимому, никто другой тоже. - person Ashley Clark; 11.01.2010
comment
Невероятно, как долго я искал испытания «один-ко-многим» на пустые отношения. Так рада, что вы разместили это здесь! - person Joseph DeCarlo; 17.11.2012
comment
Спасибо за это. Вытащил меня из места. - person nicktones; 17.05.2013
comment
Спасибо за это! Почему в документации мне предлагается использовать массив [SIZE], если он не работает ?! Не говоря уже о "@count" нигде. - person michael.zischka; 11.07.2014
comment
Следует отметить, что модификатор ALL вообще не поддерживается в предикатах с Core Data при использовании типа хранилища SQLite. - person Andrew; 28.02.2018

с вашей помощью мне наконец удалось определить правильный предикат для моего сценария. Похоже, что объект NSDate обрабатывается как double, однако double никогда не бывает чем-то вроде 3.7, он всегда как 3.0 Следовательно, следующий предикат корректно работает в моих тестах:

NSPredicate *occurrenceIsNotExcludedPredicate = [NSPredicate predicateWithFormat: @"(excludedOccurrences.@count == 0 || (excludedOccurrences.@count > 0 && NONE excludedOccurrences.start == %@))",thisDate];

где thisDate - это объект NSDate, содержащий только компоненты дня, месяца и года (как в случае свойства start объекта ExcludedOccurrence.

Тестирование на пустые отношения в основном выполняется с использованием агрегатного оператора @count, как предлагают некоторые люди в Apple.

Еще раз большое спасибо за вашу помощь. Я до сих пор замечаю, что документация содержит изъяны в нескольких частях (особенно там, где говорится, что ВСЕ работает нормально, а вместо этого не работает вообще).

person Massimo Cafaro    schedule 29.07.2009

Итак, чтобы проверить непустые отношения, это действительно работает:

[NSPredicate predicateWithFormat:@"relationship.@count != 0"]

Решение, данное Эшли Кларк, вылетает из-за того, что я даю «многим ключ, не разрешенный здесь»

person Simon Woodside    schedule 11.01.2010
comment
Я исправил свой ответ, не знаю, о чем я думал, когда писал это. Моя вина. - person Ashley Clark; 11.01.2010

А в swift 2 что-то вроде:

request.predicate = NSPredicate(format: " relationship.@count != 0")
person Steve    schedule 27.11.2015