1

I have a Core Data database with an entity "Event" and an attribute "eventDate" with "Date" type. The task is showing events grouping by date and showing the number (@"count") of events date by date. For example eventDate (mm-dd-yyyy) data:

events     eventDate
event 1    01-01-2013
event 2    01-01-2013
event 3    01-02-2013
event 4    01-03-2013
...

Result in table view:

date         count
01-01-2013     2
01-02-2013     1
01-03-2013     1
...

Don't like to fetch all database as it could be big so I use aggregate operation not to fetch every object. The code is working without error but the resulting array is empty. My guess the problem is the grouping with date type attribute and the NSAttribute/attributeType but couldn't make it work. The code in the Event's category file is:

+ (NSArray *)aggregateOperationOnEvent:(NSString *)attributeName withFunction:(NSString *)function withPredicate:(NSPredicate *)predicate inManagedObjectContext: (NSManagedObjectContext*)context {

NSEntityDescription* entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:context];

NSAttributeDescription* attributeDesc = [entity.attributesByName objectForKey:attributeName];


NSExpression *keyPathExpression = [NSExpression expressionForKeyPath: attributeName];
NSExpression *functionExpression = [NSExpression expressionForFunction: [NSString stringWithFormat:@"%@:", function] arguments: [NSArray arrayWithObject:keyPathExpression]];

NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName: function];
[expressionDescription setExpression: functionExpression];
[expressionDescription setExpressionResultType: NSInteger32AttributeType];


NSFetchRequest* request = [NSFetchRequest fetchRequestWithEntityName:@"Event"];

[request setPropertiesToFetch:[NSArray arrayWithObjects:attributeDesc, expressionDescription, nil]];
[request setPropertiesToGroupBy:[NSArray arrayWithObject:attributeDesc]];
[request setResultType:NSDictionaryResultType];

if (predicate != nil)
    [request setPredicate:predicate];

NSError* error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];

return results;

}

BootMaker
  • 1,639
  • 1
  • 22
  • 24

2 Answers2

0

Aggregating on a NSDate is not a good idea, since it's backed by a floating point type. Things might be easier if you store something like days since reference date as an int32_t. You need to use NSDateComponents:

@implementation NSDate (Days)

-  (NSInteger)daysSinceReferenceDate;
{
    NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *comp = [cal components:NSDayCalendarUnit fromDate:[NSDate dateWithTimeIntervalSinceReferenceDate:0] toDate:self options:0];
    return [comp day];
}

@end
Daniel Eggert
  • 6,665
  • 2
  • 25
  • 41
  • Your solution has some problems. As I mentioned I need the dates as a "labels" of the tableView cells. I don't think that NSDate could be problem in this context as in the Apple docs there is a code snippet with NSDate in the form of [expressionDescription setExpressionResultType:NSDateAttributeType]; The function is @"count" but could be anything else as @"min" etc. I tried @[attributesName] version earlier...without success. – BootMaker Feb 12 '13 at 20:52
0

The only problem was when I transferred the "results" array to another array the latter's allocation code accidentally commented out, this is why I got empty array in the NSLog. So the GOOD NEWS it's possible to use aggregate operation on DATE attribute and the solution is above. The "results" array's printout:

 2013-02-13 19:19:48.063 YourAppsName[35147:c07] -------- results = (
    {
    count = 2;
    eventDate = "2013-01-01 00:00:00 +0000";
},
    {
    count = 1;
    eventDate = "2013-01-02 00:00:00 +0000";
},
    {
    count = 1;
    eventDate = "2013-01-03 00:00:00 +0000";
}

)

Isuru
  • 30,617
  • 60
  • 187
  • 303
BootMaker
  • 1,639
  • 1
  • 22
  • 24