使用 Core Data 时,如何正确设置一对多关系的 NSPredicate? [英] How to correctly setup a NSPredicate for a to-many relationship when using Core Data?

查看:18
本文介绍了使用 Core Data 时,如何正确设置一对多关系的 NSPredicate?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个核心数据模型,其中任务实体包含一个可选的对多关系 ExcludedDays 到 ExcludedDay 实体.ExcludedDay 的属性之一是 day,它是一个 NSDate 对象.ExcludedDay 实体与 Task 实体具有反向强制一对一关系.

I have a Core Data model in which a Task entity includes an optional to-many relationship ExcludedDays to the ExcludedDay entity. One of the properties of ExcludedDay is day, which is an NSDate object. The ExcludedDay entity has an inverse mandatory to-one relationship to the Task entity.

为了获取指定日期的任务,我需要确保指定日期不会作为任何 ExludedDay 实体的日期属性出现.

In order to fetch the tasks for a specified day, I need to make sure that the specified day does not appear as the day property of any ExludedDay entity.

我开始尝试

NSPredicate *dayIsNotExcludedPredicate = [NSPredicate predicateWithFormat: @"ALL excludedDays.day != %@", today];

然而,不管文档怎么说,ALL 都不起作用,应用程序抛出异常:由于未捕获的异常‘NSInvalidArgumentException’,终止应用程序,原因:‘不支持的谓词.

However, despite what the documentation says, ALL does not work and the application throws an exception: Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘Unsupported predicate.

在这个论坛上发布同样的问题后,我在很多人的帮助下设计了以下谓词:

After posting the same question in this forum, I was able to devise the following predicate with the help of various people:

NSPredicate * dayIsNotExcludedPredicate = [NSPredicate predicateWithFormat: @"excludedDays.@count == 0 || (excludedDays.@count > 0 && NONE excludedDays.day == %@))", today];

虽然这最初有效,但我刚刚发现这只适用于 ExcludedDay 实体仅包含一天的情况.一旦 ExcludedDay 实体包含超过一天的同一任务,该谓词就会停止工作.结果,即使一天在 ExcludedDay 实体中显示为一天,但仍选择了一天的任务,这当然是错误的.问题与作为 NSDate 对象的属性 day 无关:用相应的 NSString 或等效的整数替换 day,我仍然面临同样的问题和不正确的行为.

While this worked at first, I have just discovered that this only works when the ExcludedDay entity contains ONLY one day. As soon as the ExcludedDay entity contains more than one day for the same task, this predicate stops working. As a result, a task is selected for a day even though the day appears as a day in the ExcludedDay entity, which is of course wrong. The problem is not tied to the property day being a NSDate object: replacing day with the corresponding NSString or equivalently with an integer, I still face the same issue and incorrect behaviour.

在这种情况下实现谓词的正确方法是什么?在使用核心数据时,这可能是与 ANY 聚合运算符相关的错误吗?提前谢谢你,这让我发疯了.

What is the correct way to implement the predicate in this case? May this be a bug related to the ANY aggregate operator when using core data? Thank you in advance, this is now driving me crazy.

推荐答案

事实证明,这是缺少和/或不一致文档的另一个问题.

It turns out this is yet another problem with missing and/or inconsistent documentation.

这种情况下正确的谓词如下:

The correct predicate in this case is the following one:

[NSPredicate predicateWithFormat:@"(excludedOccurrences.@count == 0) OR (0 == SUBQUERY(excludedOccurrences, $sub, $sub.day == %@).@count)", today]

在谓词中,使用子查询来测试日期与您的测试日期匹配的相关excludedOccurrences 的数量是否为零.但是,文档具有误导性.以下是谓词编程指南关于将谓词与对多关系结合使用的说明.

In the predicate, a subquery is used to test if the number of related excludedOccurrences with a date matching your test date is equal to zero. However, the documentation is misleading. Here is what the Predicate Programming Guide says regarding the use of predicates in conjunction with to-many relationships.

在关系中使用谓词

如果使用一对多关系,谓词的构造略有不同.例如,如果要获取其中至少有一个员工的名字为Matthew"的部门,请使用 ANY 运算符,如下例所示:

If you use a to-many relationship, the construction of a predicate is slightly different. If you want to fetch Departments in which at least one of the employees has the first name "Matthew," for instance, you use an ANY operator as shown in the following example:

NSPredicate *predicate = [NSPredicate predicateWithFormat:
    @"ANY employees.firstName like 'Matthew'"];

如果您想查找所有员工的工资都超过特定金额的部门,请使用 ALL 运算符,如下例所示:

If you want to find Departments in which all the employees are paid more than a certain amount, you use an ALL operator as shown in the following example:

float salary = ... ;
NSPredicate *predicate = [NSPredicate predicateWithFormat:
    @"ALL employees.salary > %f", salary];

这篇关于使用 Core Data 时,如何正确设置一对多关系的 NSPredicate?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆