26

我正在玩一个使用 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 一起使用?还是我构造不当?

谢谢!

4

2 回答 2

24

因此,看来我们已经在对原始帖子的评论中确定这可能是由于 SQLite 存储与块谓词不兼容造成的,因为 Core Data 无法将这些转换为 SQL 以在存储中运行它们(感谢 JoostK)。

可能有几种方法可以克服这个问题:

  • 假设您的实体的结束日期是一个常规属性,您可能能够将到期约束表示为谓词格式字符串而不是块谓词,Core Data 应该能够将其转换为 SQL 子句。
  • 如果上述情况可行,您可能更喜欢使用获取请求模板来检索过期项目。不过,您需要传入一个替换变量,例如$NOW提供对当前日期的访问权限。这具有使谓词模板显示在模型编辑器中的优点。
  • 然而,这两种方法都有重复现有功能(即您的isExpired方法)的缺点。因此,另一种方法是首先获取所有符合条件的实体,而不管它们的到期状态如何,然后对结果实体集运行专门的过滤步骤以清除未到期的实体。由于到那时,它们已经从商店中完全复活,因此您应该可以为此使用块谓词。
于 2010-08-23T07:18:38.307 回答
7

您可以在不指定谓词的情况下执行正常的获取请求,然后过滤结果数组:

NSArray *allEvents = [context executeFetchRequest:fetchRequest];

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

NSArray *expiredEvents = [allEvents filteredArrayUsingPredicate:predicate];
于 2011-06-15T11:37:48.990 回答