Reputation: 475
I am using core data to fetch a list of objects. These objects have a property named 'categories'. This categories property is a NSDictionary constructed from json like :
@{@"A":@YES, @"B":@NO, @"C":@YES}
I want to get all core data objects which category is true for a given category key. I tried :
NSString *categoryKey = @"A";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"categories.%K == YES", categoryKey]];
// or
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.categories.%@ == YES", categoryKey]];
// or
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"categories[%@] == YES", categoryKey];
// Throws exception : Unsupported function expression categories["A"]
// or
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"categories[%K] == YES", categoryKey];
// Throws exception : Unsupported function expression categories[A]
// or
NSString *categoryKeyPath = [NSString stringWithFormat:@"categories.%@", categoryKey];
NSPredicate *p = [NSPredicate predicateWithFormat:@"%K == YES", categoryKeyPath]];
But it always returns empty array when performing my fetch (of course I have some objects with categories[@"A"] = YES
).
I think the problem comes from nested dictionary key path but I can't find a way to achieve this with one predicate.
Edit:
To clarify I would use
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [[evaluatedObject.categories objectForKey:categoryKey] boolValue];
}];
But predicateWithBlock:
is not supported when fetching in core data.
Upvotes: 0
Views: 905
Reputation: 2968
Try this
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.categories LIKE \"%@\":true", categoryKey]];
Upvotes: 0
Reputation: 1547
If I understand correctly categories
is a string attribute on your entity, which contains JSON data, and your managed objects parse this JSON so it can be read as a dictionary.
The problem is that the managed objects are not created before the fetch is performed. At that point, categories
is just a string, and no key path will be able to extract the info you want from it. You will need to fetch all the objects so they can construct their dictionaries, then filter that collection. For large data sets, this may be slow.
Core Data is designed to be used by explicitly modelling the data; if you jam your own data structure inside a string, Core Data can’t help you. The more idiomatic design would be to have a Categories
entity with a to-many/to-many relationship with the entity of your object. This makes it trivial to find all the objects in category A by fetching category A then following the relationship.
Upvotes: 1