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

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

问题描述

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



为了获取指定日期的任务,我需要确保指定的



我开始尝试

 

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

然而,尽管文档说过,所有的都不工作,应用程序抛出异常:由于未捕获的异常'NSInvalidArgumentException',原因:'不支持的谓词。



在此论坛发布相同的问题后,我能够设计以下谓词与帮助各种人:

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

虽然这起作用,我刚刚发现,只有当ExcludedDay实体只包含一个天。一旦ExcludedDay实体对同一任务包含多于一天,此谓词就会停止工作。因此,即使该日在ExcludedDay实体中显示为天,这当然也是一天中选择的任务,这当然是错误的。问题不是绑定到属性一天是一个NSDate对象:用相应的NSString替换日或等价地用整数,我仍然面临同样的问题和不正确的行为。



在这种情况下,实现谓词的正确方法是什么?在使用核心数据时,这可能是与ANY聚合运算符相关的错误?

解决方案

事实证明,这是另一个问题




$ b

正确的谓词在这种情况下是以下的:

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

在谓词中,子查询用于测试与日期匹配的相关excludedOccurrences的数量您的测试日期等于零。但是,文档是误导。这是谓词编程指南关于谓词与一对多关系的结合使用的说明。



使用谓词和关系



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

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

如果您想查找所有员工都支付超过一定金额的部门, ALL运算符,如以下示例所示:

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


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.

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.

I started trying

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

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];

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.

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]

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.

Using Predicates with Relationships

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'"];

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天全站免登陆