Как мне настроить NSPredicate для поиска объектов с атрибутом nil

#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:

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Predicates/Articles/pUsing.html#//apple_ref/doc/uid/TP40001794-SW4

следующий код должен работать

 predicate = [NSPredicate predicateWithFormat:@"firstName = nil"];
  

Ответ №4:

Существует очень раздражающее поведение запросов на выборку, как задокументировано Apple:

Если объект в контексте был изменен, предикат вычисляется по его измененному состоянию, а не по текущему состоянию в постоянном хранилище. Следовательно, если объект в контексте был изменен таким образом, что он соответствует критериям запроса на выборку, запрос извлекает его, даже если изменения не были сохранены в хранилище и значения в хранилище таковы, что он не соответствует критериям. И наоборот, если объект в контексте был изменен таким образом, что он не соответствует запросу на выборку, запрос на выборку не извлечет его, даже если версия в хранилище действительно совпадает.

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

Моим единственным советом было бы координировать доступ к контексту управляемого объекта (скажем, на NSOperationQueue ) таким образом, чтобы любые обновления могли быть сохранены в постоянном хранилище перед выполнением запроса на выборку.