Anders
Anders

Reputation: 2941

NSPredicate with to-many relationship

I have a one-to-many relationship between two models, user <-->> followers, the followers table consists of userIds. I want to make a fetch request to get the associated users to theese userIds. My predicate currently looks like this:

predicate = [NSPredicate predicateWithFormat:@"ANY userId IN %@", self.user.followers];

This results in 0 results. I wonder how this predicate should look like?

Update

The code I use for adding follower objects to user's (from JSON data):

+ (void)insertFollowersFromDict:(NSDictionary *)dictionary forUser:(User *)user  inManagedObjectContext:(NSManagedObjectContext*)moc
{
    NSArray *followers = [dictionary objectForKey:@"data"];

    if (followers.count != 0) {
        NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Follower" inManagedObjectContext:moc];
        for (NSString *followerId in followers) {
            Follower *newFollower = [[Follower alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:moc];
            NSNumberFormatter * numberFormatter = [[NSNumberFormatter alloc] init];
            newFollower.user = [User findUser:[numberFormatter  numberFromString:followingId] inManagedObjectContext:moc];
            [user addFollowersObject:newFollower];
        }
    }
}

Code I use to configure cells in my tableview:

// This for some reason always result in the same user. 
Follower *follower = [self.fetchedResultsController objectAtIndexPath:indexPath];
User *cellUser = follower.user;

// Always self.user
cell.text = cellUser.name

------------------------
I Anders               I
------------------------
------------------------
I Anders               I 
------------------------

I'm not sure why this happens.

Upvotes: 0

Views: 357

Answers (2)

Lorenzo B
Lorenzo B

Reputation: 33428

Anders,

I'll try to provide some details about the model I think is well suitable for let your app working.

First, your model should look like the following (I skipped attributes, as you can see).

enter image description here

An User is linked to zero or many Followers.

Let me know discuss about relationships.

followers is a to-many relationship to Follower entity. It is set like this.

enter image description here

As you can see, the rel is optional since an user cannot have any follower. The delete rule is cascade since if you delete an user, also its followers will be deleted.

user on the contrary is to-one rel to an user. It looks like this.

enter image description here

It's not optional since a follower can exist only with an user. It's nullify since if you delete a follower, the change will no have effect to the associated user.

NOTE I created the model based on the specs you provide, but I think it could also be extended to fit a many-to-many relationship. This means: different users can have the same followers.

Now, if you create a fetch request against Follower, you can retrieve all the followers that belong to a specific user in the following way.

NSFetchRequest* request = [NSFetchRequest fetchRequestWithEntityName:@"Follower"]
[request setPredicate:[NSPredicate predicateWithFormat:@"user == %@", self.user]];
NSArray* results = // execute the request here

// results will contain the followers for a specific user (i.e. the one you used in the predicate)

Hope that helps.

Edit

NSManagedObject* follower = [followerResults objectAtIndex:[indexPath row]]; // this gives you a follower, put some error control if followerResults has no elements
NSManagedObject* user = [follower objectForKey:@"user"]; // this gives you the user associated to that follower

Edit 2

I have no clear what you mean but the behavior is correct since you are using

cell.text = cellUser.name

In this way you retrieve the name associated to the user. There is only one user associated to that set of followers.

e.g. user Andrew has zero or many followers (Mike, Bob, Todd).

The fetch request you use does the following: Give me all the followers where the user is Andrew.

If you want to display the followers change like

cell.text = follower.name; // if Follower entity has a name attribute

VERY VERY VERY IMPORTANT

Add a new attribute (NOT a relationship) to your Follower entity. Called it name and make it of type NSString. As you did for the User entity (I suppose).

Then, when you create a new Follower object you will set it like

 newFollower.user = // set the user
 newFollower.name = // set the name

I really suggest to understand the difference bewteen ATTRIBUTES and RELATIONSHIPS.

The former are properties of a specific entity (e.g. name, age, gender). The latter are links among entities.

Upvotes: 3

Levi
Levi

Reputation: 7343

You should have a relationship between objects. You don't have to store the userID in the Follower object. This way you can simply write:

predicate = [NSPredicate predicateWithFormat:@"user = %@", self.user];

This would return all the Followers that have a relationship to self.user. Hope this helps.

Upvotes: 3

Related Questions