【问题标题】:NSFetchRequest and predicateWithBlockNSFetchRequest 和 predicateWithBlock
【发布时间】:2011-04-02 08:59:29
【问题描述】:

我正在玩一个使用 Core Data 和 NSManagedObjects 来填充 UITableView 的应用程序。我的应用程序中只有一个类,称为Event。我在Event 上创建了以下自定义实例方法:

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

我想将显示Event 对象的UITableView 限制为仅显示过期的事件——即isExpired 返回YES。我试图通过在NSFetchRequest 中添加NSPredicate 来做到这一点:

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

谢谢!

【问题讨论】:

  • 我注意到predicateWithBlock 的文档指出“在 Mac OS X v10.6 中,Core Data 在内存和原子存储中支持此方法,但在基于 SQLite 的存储中不支持。”不过,没有关于这是否/如何影响 iOS(您的场景)的消息。您不会碰巧经营 SQLite 商店,因此这可能会影响您吗?
  • @ig2r 这实际上是问题的答案。是的,iOS 也是如此。将打开并读取原子存储,您将创建所有 NSManagedObjects,因此您可以向它们调用消息。内存存储也是如此。但是对于 SQLite,NSManagedObjects 仅在商店请求时创建。将基于获取请求创建 SQLite SELECT 语句,同时考虑谓词。所以谓词在对象创建之前就已经应用了,因此你不能在它们上调用消息。
  • @ig2r & Joost 你能否请您在文档中这样提到它的位置?我有一种情况,我无法避免使用 predicateWithBlock 创建 FetchedResultsController。

标签: objective-c core-data nsfetchedresultscontroller nsfetchrequest


【解决方案1】:

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

可能有几种方法可以解决这个问题:

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

【讨论】:

  • 那么,如果不使用谓词,这又是如何实现的呢? (对不起,我是新人,所以它不会让我在 cmets 中回复)
【解决方案2】:

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

NSArray *allEvents = [context executeFetchRequest:fetchRequest];

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

NSArray *expiredEvents = [allEvents filteredArrayUsingPredicate:predicate];

【讨论】:

  • 但我们不能将这种两步技术与 NSFetchedResultsController 一起使用,对吧?
  • Exactlt Martin,重点是您可以使用NSFetchedResultsController 的任何好处,例如方法委托
猜你喜欢
  • 1970-01-01
  • 2021-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-28
相关资源
最近更新 更多