Search code examples
ioscore-datamany-to-manynspredicatensfetchrequest

Core Data filter to many ordered relationship with predicate


I have a Core Data model with Task and List, where List has a to-many ordered relationship to Task, and Task has the inverse to-many relationship to List. I need to retrieve Tasks from a given List in the correct order, but filtered to match a predicate. For example, if priority is a field on Task,

NSPredicate* predicate = [NSPredicate predicateWithString:@"priority == HIGH"]

List* list; // already fetched 

I can accomplish it by

NSArray* allTasks = list.tasks;
NSArray* someTasks = [allTasks filteredArrayUsingPredicate:predicate];

but that requires pulling all the tasks into memory. I could just fetch the tasks directly

NSFetchRequest* req = [[NSFetchRequest alloc] initWithEntityName:@"Task"];
[req setPredicate:[NSPredicate predicateWithFormat:@"list == %@ AND priority == HIGH", list]];
NSArray* someTasks = [context executeFetchRequest:req error:&error];

but then the task order is not preserved.

Is there a way to filter the relationship fault by a predicate?


Solution

  • I think the following method will work, though it is very inefficient:

    1. Fetch the required Tasks using your desired predicate, ensuring that the fetch request's returnsObjectsAsFaults property is set to true.
    2. Create a new predicate with format "SELF IN %@", passing the array of tasks (from step 1) as the argument.
    3. Filter the ordered set (list.tasks) using the new predicate.

    That way the predicate is evaluated in the store, without faulting in the tasks, while the order is still determined by the ordered relationship.