28 Aug 2009, 15:37
Generic-user-small

Massimo Cafaro (4 posts)

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.

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.

02 Sep 2009, 17:59
Avatarsmall_pragsmall

Marcus S. Zarra (245 posts)

You need to look into using the @IN@ keyword more than likely as you are looking inside of a SET being returned as opposed to a single object. Review the NSPredicate API for some of the functionality offered by it to work with groups of objects.

19 Sep 2009, 14:27
Generic-user-small

Massimo Cafaro (4 posts)

I believe this could be extremely useful to many people. 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 practice, the ONLY way to setup a correct predicate when dealing with Core Data and to-many relationships is to use a subquery embedded within the predicate. Nothing else will work.

  You must be logged in to comment