NSFetchRequest 和 predicateWithBlock

发布于 2024-09-15 16:18:41 字数 843 浏览 5 评论 0原文

我正在玩一个使用 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];

但收到错误:*** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“子谓词 BLOCKPREDICATE(0x272ac) 出现问题” ***。这是否意味着您不能将块谓词与 NSFetchRequest 一起使用?或者我只是构建不当?

谢谢你!

I am playing with an app that uses Core Data and NSManagedObjects to populate a UITableView. There is only one class in my application, called Event. I have created the following custom instance method on Event:

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

I would like to limit the UITableView that displays Event objects to only the Events that are expired - that is, where isExpired returns YES. I have tried to do this by adding an NSPredicate to the NSFetchRequest:

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

but I get the error: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Problem with subpredicate BLOCKPREDICATE(0x272ac)'
***
. Does this mean that you can't use a block predicate with an NSFetchRequest? Or have I just constructed it improperly?

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

原来分手还会想你 2024-09-22 16:18:41

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

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

  • 如果实体的结束日期是常规属性,您可以将到期约束表示为谓词格式字符串而不是块谓词,核心数据应该能够做到这一点翻译成 SQL 子句。
  • 如果上述情况可行,您可能更喜欢使用 获取请求模板以检索过期项目。不过,您需要传入一个替换变量,例如 $NOW 才能访问当前日期。这样做的优点是使谓词模板显示在模型编辑器中。
  • 然而,这两种方法都有重复现有功能的缺点(即您的 isExpired 方法)。因此,另一种方法是首先获取所有合格实体,无论其过期状态如何,然后对结果实体集运行专用过滤步骤以清除未过期的实体。因为到那时,它们已经从商店中完全复活,您应该能够为此使用块谓词。

So, it appears that we've established in the comments to the original post that this is likely caused by SQLite stores being incompatible with block predicates, since Core Data cannot translate these to SQL to run them in the store (thanks, JoostK).

There might be a couple of ways to overcome this:

  • Provided that the end date of your entities is a regular attribute, you might be able to express the expiry constraint as a predicate format string instead of a block predicate, which Core Data should be able to translate into a SQL clause.
  • If the above is possible, you will probably prefer to use a fetch request template to retrieve the expired items. You would need to pass in a substitution variable like $NOW to give access to the current date, though. This has the advantage of making the predicate template show up in the model editor.
  • Both approaches, however, have the disadvantage of duplicating existing functionality (i.e., your isExpired method). So another way would be fetch all qualifiying entities regardless of their expiry state first, and then run a dedicated filtering step on the resulting set of entities to weed out the non-expired ones. Since by that point, they have been fully resurrected from the store, you should be able to use a block predicate for this.
南街女流氓 2024-09-22 16:18:41

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

NSArray *allEvents = [context executeFetchRequest:fetchRequest];

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

NSArray *expiredEvents = [allEvents filteredArrayUsingPredicate:predicate];

You can do a normal fetch request without specifying the predicate, and afterwards filter the resulting array:

NSArray *allEvents = [context executeFetchRequest:fetchRequest];

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

NSArray *expiredEvents = [allEvents filteredArrayUsingPredicate:predicate];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文