I encountered the same errors as you. It seems that although you can get a set of employees and perform on it some set of aggregate operations by doing something like:
Department * dept =; NSSet * employees = dept.employees; NSNumber * sumOfHoursWorked = [employee valueForKeyPath: @ "@ sum.hoursWorked"];
There when you connect, there is a difference. Bindings are asked to follow a key path, rather than evaluate it once. Given what this looks like, sorta makes sense why you can't get attached to these key paths. Like. Varieties.
Now. As for the solution, what I usually do in such cases is to write a tiny little subclass of NSValueTransformer to do what I need and then connect it to IB. Thus, I write ten lines of code that I need, but I donโt end up making a complete NSTableView data source due to the lack of a simple aggregate. In this case, you can do something like this:
// Declaration @interface MySumOfHoursWorkedTransformer : NSValueTransformer @end @interface MyNumberOfRacesTransformer : NSValueTransformer @end // Implementation @implementation MySumOfHoursWorkedTransformer + (Class)transformedValueClass { return [NSNumber class]; } // class of the "output" objects, as returned by transformedValue: + (BOOL)allowsReverseTransformation { return NO; } // flag indicating whether transformation is read-only or not - (id)transformedValue:(id)value // by default returns value { NSNumber* retVal = nil; if ([value isMemberOfClass: [Department class]]) { double hoursWorked = 0.0; for (Employee* employee in [value valueForKey: @"employees"]) { NSNumber* hoursWorkedNumber = employee.hoursWorked; hoursWorked += hoursWorkedNumber ? [hoursWorkedNumber doubleValue] : 0.0; } retVal = [NSNumber numberWithDouble: hoursWorked]; } return retVal; } @end @implementation MyNumberOfRacesTransformer + (Class)transformedValueClass { return [NSNumber class]; } // class of the "output" objects, as returned by transformedValue: + (BOOL)allowsReverseTransformation { return NO; } // flag indicating whether transformation is read-only or not - (id)transformedValue:(id)value // by default returns value { NSNumber* retVal = nil; if ([value isMemberOfClass: [Department class]]) { NSMutableSet* raceSet = [NSMutableSet set]; for (Employee* employee in [value valueForKey: @"employees"]) { id raceVal = employee.race; if (raceVal) [raceSet addObject: raceVal]; } retVal = [NSNumber numberWithUnsignedInteger: raceSet.count]; } return retVal; } @end
Then just bind these TableColumns to ArrayController.arrangedObjects and connect the corresponding value transformer subsystem. Now you cannot edit these values, but what would it mean to change the aggregate value?
Hope this helps. I used this approach in conjunction, and he is sure that he will refuse the bindings.
source share