CodeNoob
CodeNoob

Reputation: 250

HowTo create predicate for object count several relationships deep? Core Data iOS Swift

I have a rather vexing issue that I have not yet been able to find an answer to, and was hoping you could help! My situation is this: I have the following object model in Core Data

Scenes <-->>Characters<-->>Lines

The entities have the relationships: Scenes->toCharacters->Characters->toLines->Lines

What I am trying to accomplish is to fetch all Scenes where there exist characters who actually have lines.

Every article I've read talks about simply "Walking The Graph", and this DOES work, but not all the way down to the Lines entity.

For example, this predicate works just fine, goes one level deep and retrieves all scenes which contain characters:

    let scene_ent:NSEntityDescription = NSEntityDescription.entityForName("Scenes", inManagedObjectContext: context)

    scenerequest.entity = scene_ent

    let predicate:NSPredicate = NSPredicate(format: "toCharacters.@count > 0")        
    scenerequest.predicate = predicate

When I try to modify the predicate to instead retrieve all scenes which contain characters who have lines:

    let predicate:NSPredicate = NSPredicate(format: "toCharacters.Characters.toLines.@count > 0")   

I get the error 'Unsupported function expression count:(toCharacters.Characters.toLines)'

Is there something really simple that I'm missing here?

thanks!

Upvotes: 9

Views: 5121

Answers (1)

Martin R
Martin R

Reputation: 539815

The key paths in the predicate use only the relationships, not the entity names, so

NSPredicate(format: "toCharacters.Characters.toLines.@count > 0")

should be

NSPredicate(format: "toCharacters.toLines.@count > 0")

but that will probably not work either. This might work (cannot test this at the moment):

NSPredicate(format: "ANY toCharacters.toLines.@count > 0")

and I am quite sure that this will work:

NSPredicate(format: "SUBQUERY(toCharacters, $c, $c.toLines.@count > 0).@count > 0")

Update: The correct solution is

NSPredicate(format: "SUBQUERY(toCharacters, $c, ANY $c.toLines != NULL).@count > 0")

Upvotes: 15

Related Questions