I have an NSFetchRequest
set to fetch properties with enough information to populate a row displaying a user - their company, name, etc, and the number of things assigned to them. I send this to an NSFetchedResultsController
which I'm using to populate rows in a table.
The property I'm having trouble with is the count of assigned items. A user can be a part of multiple projects, and I only care about issues within the current project and in a certain set of states.
So I have a predicate set up to get all issues assigned to this user, both in this project and in a given set of states:
NSPredicate* sequenceStatePredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[
[NSPredicate predicateWithFormat:@"$assignment.workItem.sequence.project == %@", project],
[NSPredicate predicateWithFormat:@"$assignment.workItem.sequence.state IN %@", [WorkSequence countableStates]]
]];
I then set up a count:
expression for that predicate, on the assignments
relationship of the user:
NSExpression *assignments = [NSExpression expressionForSubquery:[NSExpression expressionForKeyPath:@"assignments"] usingIteratorVariable:@"assignment" predicate:sequenceStatePredicate];
NSExpression *count = [NSExpression expressionForFunction:@"count:" arguments:@[assignments]];
NSExpressionDescription *sequenceCountProperty = [[NSExpressionDescription alloc] init];
[sequenceCountProperty setExpression:count];
[sequenceCountProperty setExpressionResultType:NSInteger32AttributeType];
[sequenceCountProperty setName:WorkSequenceCount];
Finally, I set this expression as a property for my fetch request:
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[User entityName]];
[fetchRequest setResultType:NSDictionaryResultType];
[fetchRequest setPropertiesToFetch:@[/* Some other properties */, sequenceCountProperty]];
[fetchRequest setPredicate:query.predicate];
...
This all works fine - except the result I get in the dictionary for the WorkSequenceCount
key is an NSManagedObjectID
, not an integer.
(lldb) po [[[[_fetchedResultsController fetchedObjects] objectAtIndex:0] objectForKey:WorkSequenceCount] class]
_NSCoreDataTaggedObjectID
The object ID appears to be equivalent to the expected count (note the p50 at the end - I expect the count to be 50 here, and I only have 3 Project objects in CoreData at this time):
(lldb) po [[[_fetchedResultsController fetchedObjects] objectAtIndex:0] objectForKey:WorkSequenceCount]
0xd000000000c80008 <x-coredata://1EB42655-9F98-4DFD-8A7A-BB65A108D300/Project/p50>
And the property expression is correct:
(lldb) po [[[[_fetchedResultsController fetchRequest] propertiesToFetch] objectAtIndex:4] expression]
count:(SUBQUERY(assignments, $assignment, $assignment.workItem.sequence.state IN {1, 2, 3, 5} AND $assignment.workItem.sequence.project == 0x16f93a90 <x-coredata://70C4F650-DADF-462C-A10A-55DA1E5978D3/Project/p1>))
...as is its result type (0x000000c8 == 200 == NSInteger32AttributeType):
(lldb) po [[[[_fetchedResultsController fetchRequest] propertiesToFetch] objectAtIndex:4] expressionResultType]
0x000000c8
If I log the SQL and run the request by hand on the SQLite file, I get the expected results.
If I remove the project filter from the predicate, I get an integer - so this appears to be related to including that. Obviously I can't do that, because then I get the number of items assigned to the user across all projects. No matter how I build the predicate statement (swapping the order of the AND, build it as one predicate with an AND myself instead of using NSCompoundPredicate
, etc...) I can't change the result.
So, why is my fetch request returning a managed object ID when I explicitly tell it to give me an integer?
It's weird - a bug in CoreData, I think. It's certainly not honouring the expressionResultType
. I've experienced it with much simpler expressions, and dodged it by using object attributes in expressions/predicates, rather than objects themselves. eg rather than counting assignments
, try counting an attribute of the assignments
(assuming there is an attribute that you know is not nil).
User contributions licensed under CC BY-SA 3.0