#objective-c #nspredicate
#objective-c #nspredicate
Вопрос:
У меня есть a ManagedObject class
, и одним из членов класса является a NSDate
. Я хотел бы отобразить все объекты класса, для которых дата НЕ установлена. Я пытался использовать предикат, подобный этому:
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"(date = NIL)"];
Но я все еще получаю объекты, для которых установлен date
. Как правильно настроить предикат для этого?
Ответ №1:
Я думаю, что это проблема чувствительности к регистру. Вы можете использовать «nil» или «NULL», но не «NIL». У меня это работает нормально:
NSPredicate *eventWithNoEndDate = [NSPredicate predicateWithFormat:@"endDate = nil"];
Комментарии:
1. Знаете ли вы, почему формат должен быть @»EndDate = nil», а не @»EndDate == nil»? Я бы подумал наверняка, что это должен быть двойной знак равенства, но == в этом случае не дает желаемого эффекта. Странно, потому что другие сравнения предикатов работают с == .
2. @kris Я не уверен. developer.apple.com/library/mac/#documentation/Cocoa/Conceptual / … кажется, что
=
и==
эквивалентны, но примеры в developer.apple.com/library/mac/documentation/Cocoa/Conceptual /… использовать=
3. Спасибо. Я вижу, что = и == не ведут себя одинаково в этом случае, так что обращаюсь ко всем
4. Почему они не совпадают?
5.Согласно документации Apple
=
и==
эквивалентны внутри предикатов
Ответ №2:
Разобрался. Не удалось сделать это с помощью предиката в строковом формате, поэтому попробовал использовать предикат с шаблоном, и это сработало. Вот код, который выдал мне объекты, для которых конечная дата была установлена в NULL:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"endDate = $DATE"];
predicate = [predicate predicateWithSubstitutionVariables:
[NSDictionary dictionaryWithObject:[NSNull null] forKey: @"DATE"]];
Комментарии:
1. Честно говоря, я чувствовал бы себя безопаснее, делая это, чем следуя более простому примеру, который криспикс приводит ниже, учитывая синтаксические нарушения тестирования на null с помощью предикатов, которые он и Крис обсуждают.
2. Спасибо!! Но как бы вы отфильтровали, если для этого нужны две переменные фильтра? Спасибо
Ответ №3:
следующий код должен работать
predicate = [NSPredicate predicateWithFormat:@"firstName = nil"];
Ответ №4:
Существует очень раздражающее поведение запросов на выборку, как задокументировано Apple:
Если объект в контексте был изменен, предикат вычисляется по его измененному состоянию, а не по текущему состоянию в постоянном хранилище. Следовательно, если объект в контексте был изменен таким образом, что он соответствует критериям запроса на выборку, запрос извлекает его, даже если изменения не были сохранены в хранилище и значения в хранилище таковы, что он не соответствует критериям. И наоборот, если объект в контексте был изменен таким образом, что он не соответствует запросу на выборку, запрос на выборку не извлечет его, даже если версия в хранилище действительно совпадает.
Возможно, вы удаляете дату в другом месте, и запрос на выборку включает результаты, в которых дата находится nil
в памяти, но все еще установлена на диске (в постоянном хранилище), и поэтому, когда объект выходит из строя, он загружает объект с установленной датой.
Моим единственным советом было бы координировать доступ к контексту управляемого объекта (скажем, на NSOperationQueue
) таким образом, чтобы любые обновления могли быть сохранены в постоянном хранилище перед выполнением запроса на выборку.