I am trying to filter a mutable array of objects using NSPredicate and am having trouble access the level that contains the property I would like to filter on.
To give a simplified example consisting of the similar custom objects.
I have an NSMutableArray of Grandparents and I would like to find all the Grandparent Objects that have GrandChildren of age 10. Therefore the grandchildren are two levels deep from the root. Child has an age property amongst other things.
ie. Grandparents has an array property Parents and Parents has an array property Children and Children has an integer property age.
The following NSPredicate has returned no results. "SELF.parents.children.age == 10"
.
I realise that as these are nested collections this predicate is likely the wrong way to go about it but I am stuck as to how to access that level. Perhaps via a Subquery or Collection Operator but I cannot work it out.
One thing to keep in mind is that I obviously still want GrandParents that have multiple Grandchildren of different ages, one of which is aged 10.
The "obvious" solution would be the predicate:
"ANY parents.children.age == 10"
However, the "ANY" operator does not work with nested to-many relationships. Therefore, you need a SUBQUERY:
NSArray *grandParents = your array of GrandParent objects;
NSPredicate *predicate = [NSPredicate
predicateWithFormat:@"SUBQUERY(parents, $p, ANY $p.children.age == 10).@count > 0"];
NSArray *filtered = [grandParents filteredArrayUsingPredicate:predicate];
Remarks:
SELF
in the predicate is not necessary. filteredArrayUsingPredicate
applies the
predicate to each GrandParent
object in the array.Parent
of a single GrandParent
. The SUBQUERY returns the parents that have any child aged 10.
So "SUBQUERY(...).@count > 0"
evaluates to TRUE if the grandparent has at least one parent that has any child aged 10.ADDED: I just found out that it can actually be done without SUBQUERY:
NSPredicate *predicate = [NSPredicate
predicateWithFormat:@"ANY [email protected] == 10"];
works and gives the desired result. (It could be less effective than the SUBQUERY, but I did not test that.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With