How to use the “IN” Operator with a Predicate

2019-07-05 14:22发布

问题:

How to write NSPredicate to fetch the rows that matches with values in the array? E.g:

[NSPredicate predicateWithFormat:@"UserName IN %@",UserIDArray];

If UserIDArray contains ID of users, how does one fetch the user name which matches with the values in this array?

回答1:

Let me start with this advice. Core Data is not SQL. Entities are not tables. Objects are not rows. Columns are not attributes/properties. Core Data is an object graph management system that may or may not persist the object graph and may or may not use SQL far behind the scenes to do so. Trying to think of Core Data in SQL terms will cause you to completely misunderstand Core Data and result in much grief and wasted time.

Because Core Data is based on objects, when you do a fetch, you get back an array of objects. To find a particular values, you then query those objects for the values of their respective attributes.

Suppose you have the following entity:

User{
    userName:string
    userID:string
}

... and want to find all the user's whose userName correspond to an array of userID strings. You would create a NSFetchRequest and set it's entity to "User". Then you would use a predicate like this:

[NSPredicate predicateWithFormat:@"userID IN %@",arrayOfUserIDs];

The fetch will return an array of NSManagedObjects (or a subclass) configured with the attribute name keys of the User entity. To find the value of the userName attribute of each managed object in the array you would ask the object for the value of it's attribute like so:

NSString *aUserName=[aUserEntityObject valueForKey:@"userName"];

Just forget everything you know about SQL or similar database systems. Core Data is not truly a database so trying to think of it in those terms will just confuse you. Core Data is all about objects.



回答2:

You predicate is good but your questions shows that you're not fully understanding what's going on.

When you execute a fetch request, you get objects, your can't get only a part of the values you set set to the NSManagedObject objects before.

What I would do in your case is retrieving the objects matching your predicate, then use valueForKey: on the resulting NSArray to get the list of usernames.

Presuming that you have an entity like this :

User{
    name:string
    identifier:string
}

The code could be :

NSArray *ids = @[@"a", @"b", @"c"];
NSManagedObjectContext *context = self.managedObjectContext;
NSFetchRequest *userRequest = [[NSFetchRequest alloc] init];
[userRequest setEntity:[NSEntityDescription entityForName:@"User" inManagedObjectContext:context]];
[elementsRequest setPredicate:[NSPredicate predicateWithFormat:@"identifier IN %@", ids]];

NSError *error;
NSArray *result = [context executeFetchRequest:userRequest error:&error];
if (result) {
    NSArray *names = [result valueForKey:@"_id"];
    // names is : @[@"the name of a", @"the name of b", @"the name of c"]
} else {
    // TREAT YOUR ERROR
}