I have tracked down a crash users of my app on iPod Touches with iPhone OS 3.1.3 have been having: for some reason, using the "@count:" expression on the CoreData store is causing a crash. Here's the relevant code:
NSExpression *avgExpression = [NSExpression expressionForFunction:@"average:" arguments:[NSArray arrayWithObject:keyPathExpression]];
NSExpressionDescription *ed = [[NSExpressionDescription alloc] init];
[ed setName:@"avgScalar"];
[ed setExpression:avgExpression];
[ed setExpressionResultType:NSFloatAttributeType];
NSExpression *countExpression = [NSExpression expressionForFunction:@"count:" arguments:[NSArray arrayWithObject:keyPathExpression]];
NSExpressionDescription *ed2 = [[NSExpressionDescription alloc] init];
[ed2 setName:@"countScalar"];
[ed2 set开发者_运维百科Expression:countExpression];
[ed2 setExpressionResultType:NSInteger16AttributeType];
[request setPropertiesToFetch:[NSArray arrayWithObjects:ed,ed2,nil]];
When the fetch is performed, I get the following error with the crash:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -constantValue only defined for abstract class. Define -[NSKeyPathExpression constantValue]!'
If I restrict the fetch to the avgExpression (@"average:"), all works fine. There's something wonky about the @"count:" expression, so far as I can tell only on iPod Touches with iPhone OS 3.1.3. Any ideas?
I could alternately perform a full fetch and use key path operators to get the averages and counts I need. However, I worry this approach would be much more expensive. Anyone know if it is?
Here's the best solution for the older OS that I could find, taking only a small performance hit.
- Execute my fetch request for avgExpression only
Clear out the expression part of the request:
[request setPropertiesToFetch:nil]; [request setResultType:NSManagedObjectResultType];
Perform a count-only fetch:
[managedObjectContext countForFetchRequest:request error:&error];
It's clear from working through this issue that the internals of CoreData changed from iOS 3 to iOS 4. You can see this, for example, by NSLog'ing a property-focused NSFetchRequest object in both OS's.
精彩评论