我有一个核心数据模型,其中任务实体包含与 ExcludedDay 实体的可选对多关系 ExcludedDays。 ExcludedDay 的属性之一是 day,它是一个 NSDate 对象。 ExcludedDay 实体与 Task 实体具有反向强制一对一关系。
为了获取指定日期的任务,我需要确保指定日期不会显示为任何 ExludedDay 实体的 day 属性。
我开始尝试
NSPredicate *dayIsNotExcludedPredicate = [NSPredicate predicateWithFormat: @"ALL excludedDays.day != %@", today];
但是,无论文档如何说明,ALL 都不起作用,应用程序会抛出异常:由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“不支持的谓词”。
在这个论坛上发布相同的问题后,我在不同人的帮助下设计了以下谓词:
NSPredicate * dayIsNotExcludedPredicate = [NSPredicate predicateWithFormat: @"excludedDays.@count == 0 || (excludedDays.@count > 0 && NONE excludedDays.day == %@))", today];
虽然这在一开始有效,但我刚刚发现这仅在 ExcludedDay 实体仅包含一天时才有效。一旦 ExcludedDay 实体包含同一任务超过一天,该谓词就会停止工作。因此,即使该天在 ExcludedDay 实体中显示为一天,也会选择某一天的任务,这当然是错误的。这个问题与属性 day 是一个 NSDate 对象无关:用相应的 NSString 或等效的整数替换 day,我仍然面临同样的问题和不正确的行为。
在这种情况下实现谓词的正确方法是什么?这可能是使用核心数据时与 ANY 聚合运算符相关的错误吗? 预先感谢您,这让我发疯。
最佳答案
事实证明,这是文档缺失和/或不一致的另一个问题。
本例中正确的谓词如下:
[NSPredicate predicateWithFormat:@"(excludedOccurrences.@count == 0) OR (0 == SUBQUERY(excludedOccurrences, $sub, $sub.day == %@).@count)", today]
在谓词中,子查询用于测试日期与您的测试日期匹配的相关 exceptedOccurrences 的数量是否等于 0。然而,该文档具有误导性。以下是《谓词编程指南》中关于将谓词与多对多关系结合使用的内容。
使用关系谓词
如果您使用一对多关系,谓词的构造会略有不同。例如,如果您想要获取其中至少一名员工的名字为“Matthew”的部门,您可以使用 ANY 运算符,如以下示例所示:
NSPredicate *predicate = [NSPredicate predicateWithFormat:
@"ANY employees.firstName like 'Matthew'"];
如果您想要查找所有员工的工资都超过特定金额的部门,您可以使用 ALL 运算符,如以下示例所示:
float salary = ... ;
NSPredicate *predicate = [NSPredicate predicateWithFormat:
@"ALL employees.salary > %f", salary];
关于iphone - 使用 Core Data 时如何正确设置 NSPredicate 来实现一对多关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1347776/