How to correctly setup a NSPredicate for a to-many relationship when using Core Data?

后端 未结 2 1846
借酒劲吻你
借酒劲吻你 2020-12-02 09:15

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

相关标签:
2条回答
  • 2020-12-02 10:00

    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];
    
    0 讨论(0)
  • 2020-12-02 10:01

    Quite curious how to solve this I setup a little project and created the context you are using.

    NSDate *today = [NSDate date];
    NSMutableArray *objects = [NSMutableArray array];
    
    {
        NSArray *day = [NSArray arrayWithObjects:today, [today dateByAddingTimeInterval:20.0f], nil];
        NSDictionary *excludedDay = [NSDictionary dictionaryWithObject:day forKey:@"day"];
        NSDictionary *object = [NSDictionary dictionaryWithObject:excludedDay forKey:@"excludedDay"];
    
        [objects addObject:object];
    }
    
    {
        NSArray *day = [NSArray arrayWithObjects:[today dateByAddingTimeInterval:20.0f], nil];
        NSDictionary *excludedDay = [NSDictionary dictionaryWithObject:day forKey:@"day"];
        NSDictionary *object = [NSDictionary dictionaryWithObject:excludedDay forKey:@"excludedDay"];
    
        [objects addObject:object];
    }
    
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NONE excludedDay.day == %@", today];
    NSArray *filtered = [objects filteredArrayUsingPredicate:predicate];
    
    NSLog(@"%@", filtered);
    

    This gives the object when:

    1. The day array is empty
    2. The day array does not contain the 'today' date

    This does not give the object when:

    1. The day array contains the 'today'
      • It doesn't matter how many objects in the day array are
    0 讨论(0)
提交回复
热议问题