How can you reference child entity name in a predi

2020-02-09 11:59发布

I have the need to create a complex predicate for an abstract base object. I want to have separate predicate queries for different inheriting entities and key off the sub-entity type, the example below is what I would like to do, however, I have not been able to find a way to reference the entity name or type in the predicate.

NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:@"MyCommonObjectBase" inManagedObjectContext:myContext];

NSPredicate *subclassAPredicate = [NSPredicate predicateWithFormat:@"someValue > %@ && entityName = %@", 100, @"SubclassA"];
NSPredicate *subclassBPredicate = [NSPredicate predicateWithFormat:@"someValue < %@ && entityName = %@", 50, @"SubclassB"];

request.predicate = [NSCompoundPredicate orPredicateWithSubpredicates:[NSArray arrayWithObjects:subclassAPredicate, subclassBPredicate, nil]];

3条回答
疯言疯语
2楼-- · 2020-02-09 12:18

I got a response from Apple at http://bugreport.apple.com problem number 7318897:

entity.name is not a modeled property, so it's not legal. it works by accident on the binary store. The correct way to fetch subentities is to do so on the NSFetchRequest and use either setIncludesSubentities or not.

So it seems the proper solution is to have separate fetch requests and to merge the result sets after execution.

查看更多
Lonely孤独者°
3楼-- · 2020-02-09 12:19

A shot in the dark here, but what about using the className value in the predicate?

NSPredicate *subclassAPredicate = [NSPredicate predicateWithFormat:@"someValue > %d AND child.className = %@", 100, @"SubclassA"];

(Notice that you had an error in your predicate format. You were using %@ to try and substitute in an integer value (100). %@ is only used for objects. Use %d (or some other flavor) for primitives)

EDIT Found it!

You'll want to do this:

NSPredice * p = [NSPredicate predicateWithFormat:@"entity.name = %@", @"SubclassA"];

I just tested this on one of my apps and it seems to work.

-Another edit-

Here's the test that I ran, which seemed to work:

NSManagedObjectContext * c = [self managedObjectContext];
NSFetchRequest * f = [[NSFetchRequest alloc] init];
[f setEntity:[NSEntityDescription entityForName:@"AbstractFolder" inManagedObjectContext:c]];
[f setPredicate:[NSPredicate predicateWithFormat:@"entity.name = %@", @"DefaultFolder"]];
NSError * e = nil;
NSArray * a = [c executeFetchRequest:f error:&e];
[f release];
NSLog(@"%@", a);

When I run that, a logs two NSManagedObjects, both of the @"DefaultFolder" variety (which is what I was expecting). (AbstractFolder is an abstract entity. One of the child entities that inherits from it is a DefaultFolder)

查看更多
啃猪蹄的小仙女
4楼-- · 2020-02-09 12:37

The only way of associating a predicate with an entity I know of like is this:

NSPredicate * predicate = [NSPredicate predicateWithFormat: @"(%K == %@)", fieldName, fieldValue, nil];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:managedObjectContext]];
[request setPredicate:predicate];

Maybe you were referring to the field name?

Edit: the entity is associated with the request, not with the predicate.

查看更多
登录 后发表回答