Подтвердить что ты не робот

NSFetchRequest и predicateWithBlock

Я играю с приложением, которое использует Core Data и NSManagedObjects для заполнения UITableView. В моем приложении есть только один класс, называемый Event. На Event я создал следующий метод специальных экземпляров:

- (BOOL)isExpired {
    return ([[self.endOn dateAtEndOfDay] timeIntervalSinceNow] < 0);
}

Я хотел бы ограничить UITableView, который отображает объекты Event только для Истекших событий, то есть где isExpired возвращает YES. Я попытался сделать это, добавив NSPredicate в NSFetchRequest:

NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary * bindings) {return([evaluatedObject isExpired]);}];
[fetchRequest setPredicate:predicate];

но я получаю ошибку: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Problem with subpredicate BLOCKPREDICATE(0x272ac)' ***. Означает ли это, что вы не можете использовать предикат блока с NSFetchRequest? Или я просто построил его неправильно?

Спасибо!

4b9b3361

Ответ 1

Итак, похоже, что в комментариях к исходному сообщению мы установили, что это, скорее всего, вызвано тем, что хранилища SQLite несовместимы с предикатами блоков, поскольку Core Data не может перевести их в SQL для запуска их в магазине (спасибо, JoostK).

Возможно, существует несколько способов преодолеть это:

  • Если конечная дата ваших сущностей является обычным атрибутом, вы можете выразить ограничение срока действия как строку предикатного формата вместо предиката блока, которые основные данные должны иметь возможность перевести в предложение SQL.
  • Если это возможно, вы, вероятно, предпочтете использовать шаблон запроса выборки для извлечения устаревших элементов. Однако вам нужно будет передать переменную подстановки, например $NOW, чтобы предоставить доступ к текущей дате. Это имеет то преимущество, что шаблон предиката отображается в редакторе моделей.
  • Оба подхода, однако, имеют недостаток дублирования существующей функциональности (т.е. вашего метода isExpired). Таким образом, другой способ будет извлекать все качественные сущности, независимо от состояния их истечения, а затем запустить выделенный этап фильтрации на результирующем множестве объектов для отсечения неиспользуемых. Поскольку к этому моменту они были полностью воскрешены из магазина, вы должны иметь возможность использовать предикат блока для этого.

Ответ 2

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

NSArray *allEvents = [context executeFetchRequest:fetchRequest];

if (!allEvents) { // do error handling here
}

NSArray *expiredEvents = [allEvents filteredArrayUsingPredicate:predicate];