I have a to-many relationship between Entity A and Entity B (iOS Core Data app). I need to get the sum of the NSDecimalNumber attribute of all instances of Entity B from a given instance of Entity A. Does anyone have a tutorial or example of this?
Asked
Active
Viewed 1,045 times
1 Answers
2
You would use the @sum collection operator thusly:
NSNumber *theSum=[ObjectA.objectBs valueForKey:@"@sum.numericalAttribute"];

TechZen
- 64,370
- 15
- 118
- 145
-
Thanks, @TechZen. the compiler complains that it's not KeyValueCoding compliant. Do I need to set up a KeyValueObserver? If so, does that code go in the model class or in my controller class? Thanks again. – JohnnyRedTruss Mar 10 '11 at 11:51
-
ManagedObjects are automatically key-value compliant. You have to be careful to use the right keypath. So, if your attribute is named `total` then the keypath would be `@sum.total`. Likewise, ObjectA.objectBs must be the correct path using the names in you model. An error saying a managedObject "is not Key-Value coding compliant for key 'whatever'" means that you've given it the wrong keypath. It's usually caused by typos. – TechZen Mar 10 '11 at 15:02
-
Thanks @TechZen. Seems I had a typo. Compiler has stopped complaining about being Key-value compliant. Now, my problem is where I put this piece of code. Maybe you could help. I have a custom table cell, where I have a label that needs to display the sum of all objectBs. Do I create a method that calculates this? Here is what I was thinking: - (void)calculateTotalCost{ NSDecimalNumber *theTotalCost = [Envelope.expenses valueForKey:"@sum.cost"]; Envelope.totalCost = theTotalCost; } Is this the right approach or am I way off base? – JohnnyRedTruss Mar 15 '11 at 18:34
-
If the calculation is purely for display, then it should go in the tableView datasource object which by default is you tableViewController. You could just drop the line into `– tableView:cellForRowAtIndexPath:` where you configure the cell for display. – TechZen Mar 15 '11 at 23:23
-
If, however, you want to include it in the data model i.e. as an attribute of an entity, then you should add a transitional attribute to the entity. Provide a custom getter for the attribute with the code and it will recalculate the sum each time the attribute is accessed e.g. for entity `Envelope` you add a transitional attribute `totalCost` and each time you use `something=anEnvelopeObj.totalCost` you get back a freshly calculated sum. – TechZen Mar 15 '11 at 23:26
-
Thanks again @TechZen for your help. Here is what I have in my configureCell: NSNumber *theSum = [Envelope.expenses valueForKey:@"@sum.cost"]; UILabel *envelopeExpensesLabel = (UILabel *) [cell viewWithTag:4]; envelopeExpensesLabel.text = theSum; The compiler is complaining that it expects a ':' before token '.' for the collection operator code line. – JohnnyRedTruss Mar 16 '11 at 11:40
-
Do you have an NSManagedObject subclass defined for `Envelope`? If not you can't use dot syntax and must use `valueForKey:` like: `[[EnvelopeObj valueForKey:@"expenses"] valueForKey:@"@sum.cost"];` If that's not the cause, then you have a missing bracket in the code before the line. – TechZen Mar 16 '11 at 13:35
-
Well that fixed the compiler complaint, @TechZen. Now when I run the app and try to add a new "Envelope", I get this error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. [
valueForUndefinedKey:]: this class is not key value coding-compliant for the key expenses. with userInfo { NSTargetObjectUserInfoKey = Envelope; NSUnknownUserInfoKey = expenses; – JohnnyRedTruss Mar 16 '11 at 14:05 -
I found this link from Jeff Lamarche http://iphonedevelopment.blogspot.com/2010/01/chapter-4-and-tale-of.html I'm thinking that if "expenses" don't exist yet, then the app crashes? – JohnnyRedTruss Mar 16 '11 at 14:25