Search code examples
iosobjective-ccore-datansexpression

Calculate the average of all NSManagedObjects' attributes


I have an entity with the name FoodItem, and it has one attribute, price (a double). Ideally, the output of this code would be:

Average Price is: 6.00

Though I'm not sure how to access the value 6.00. Can anyone assist me? Thank you

Here is my code:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"FoodItem" inManagedObjectContext:self.managedObjectContext];

NSManagedObject *o1 = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:self.managedObjectContext];
[o1 setValue:@(5.00) forKey:@"price"];

NSManagedObject *o2 = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:self.managedObjectContext];
[o2 setValue:@(7.00) forKey:@"price"];


[self.managedObjectContext save:nil];

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];


[request setSortDescriptors:@[]];

NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"price"];
NSExpression *averagePriceExpression = [NSExpression expressionForFunction:@"average:"
                                                              arguments:@[keyPathExpression]];

NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:@"averagePrice"];
[expressionDescription setExpression:averagePriceExpression];
[expressionDescription setExpressionResultType:NSDecimalAttributeType];

[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];

NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];


[controller performFetch:nil];

NSLog(@"Average price is: %@", @"");

Solution

  • I don't understand why you use a fetch results controller for this. A NSFetchedResultsController is not used for this. Use a simple NSFetchRequest for this.

    // Your previous code here
    
    // Execute the fetch.
    NSError *error = nil;
    NSArray *objects = [managedObjectContext executeFetchRequest:request error:&error];
    if (objects == nil) {
        // Handle the error.
    }
    else {
        if ([objects count] > 0) {
            NSLog(@"Average price is: %@", [[objects objectAtIndex:0] valueForKey:@"averagePrice"]);
        }
    }
    

    A simple example of this can be found from Apple doc Fetching Specific Values.