23
votes

In my Core Data model I have two entities: List and Patient. List has an attribute called 'name'.

A List can have any number of Patients and each Patient can belong to any number of different lists. I have therefore set a relationship on List called 'patients' that has an inverse to-many relationship to Patient AND a relationship on Patient called 'lists' that has a to-many relationship to List.

What I'm struggling to figure out is how to create a Predicate that will select all Patients that belong to a particular List name.

How would I go about this? I have never used relationships before in Core Data.

4

4 Answers

19
votes

This seems to work OK:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(ANY lists == %@)", myList];

Where myList is an actual List entity.

19
votes

Given a data model like:

List <<——>> Patient,

you can find all Patient instances that belong to a list with a particular name with a fetch request on the Patient entity using a predicate like:

[NSPredicate predicateWithFormat:@"ANY lists.name LIKE[cd] %@", listName]

assuming listName is an NSString instance with the list name you want. LIKE[cd] does a case-insensitive and diacritic-insensitive comparison.

12
votes

It sounds like your data model is this:

List <<-->> Patient

I would think that if you know the particular list name, then you know the particular list object. If so, you can just grab the patients using the to-many relationship from List to Patient--it is a set of patient objects. For example, if the relationship from List to Patient is named "patients":

NSSet *patientSet = listObject.patients;

Note: this requires that you create subclasses for your managed objects so you can access the attributes and relationships as properties on your objects.

If you only know the list name for some reason, and you are fetching Patient objects, then you can create a predicate using the to-many relationship from Patient to List (assume it's named "lists" and the list's name in a string named "listName"):

NSPredicate *pred = [NSPredicate predicateWithFormat:@"ANY lists.name == %@",listName];
5
votes

Ten years later, some more info !

Just some more info on the fantastic @GarryPettet answer,

Say you have entity CD_Person and aPerson is one of those. IE:

var aPerson: CDPerson

Say you have an entity CD_Pet

CD_Person has a relationship .pets which is a one-to-many CD_Pet

So just to be clear,

aPerson.pets

is indeed a Set of CD_Pet entities.

Almost certainly you'll have an id field which comes from your data source.

(Aside, .id must be an Int64 in your core data entity, even if it's a smaller int in your source data)

Two ways to go!

BOTH this

let p = NSPredicate(format: "(ANY pets == %@)", aPerson )

AND this

let p = NSPredicate(format: "(ANY pets.id == %lld)", aPerson.id)

... work perfectly, both are possibilities.

So there's two ways to go!

(PS: Don't forget the lld .. @ won't work for Int64!)

Both work fine in the common situation where you have a "many-to-many" relationship.