Predicate to sum child's value
I'm trying to get total 开发者_StackOverflow社区salary for the whole company by:
NSNumber *totalSalary = [company valueForKeyPath:@"departments.employees.@sum.salary"];
But I keep getting this error, "-[__NSSet0 decimalValue]: unrecognized selector sent to instance 0x10031eb00".
I think I'm doing something wrong but I'm not sure where.
Don't fear. Although the set and array operators in KVC are very powerful, I still find myself having to refer to the documentation almost every time I use them in complex key paths like this. Because valueForKeyPath:
is a method, you can call it from the debugger console. I often find that getting the key path right requires setting a breakpoint just before the KVC call and trying some stuff in the debugger console. Python with PyObjC (included in OSX since 10.5) is also a great interactive environment to test/debug KVC keypaths. In this particular example...
@sum
sends the -[NSNumber decimalValue]
message to each item returned by [company valueForKeyPath:@"departments.employees"]
(the "receiving array" in key-value coding language). It thus expects that each item in the receiving array is an NSNumber
. I suspect that company.departments
is a set, thus [company valueForKeyPath:@"departments.employees"]
is a set of sets, not a collection of NSNumbers
. I believe you want to create a "flattened" collection of all the employees, from which you can then calculate the sum:
id allEmployees = [company valueForKeyPath:@"departments.@distinctUnionOfSets.employees"];
NSNumber *totalSalary = [allEmployees valueForKeyPath:@"@sum.salary"];
Assuming each employee is in only one department, the following also appears to work
NSNumber *totalSalary = [company valueForKeyPath:@"departments.@sum.employees.@sum.salary"];
You appear to be traversing several collections (the collection of all departments and the collection of the employees of those departments). You'll need to union them into one container (all employees) before summing them.
Check out the @unionOf... set and array operators here:
http://tinyurl.com/yk5njks
I haven't tried this, but I think departments.@unionOfSets.employees.@sum.salary is the correct way to do it. Let me know if it's otherwise!
Update: Barry Wark beat me to it. :-) He's right, it's distinct union of sets, otherwise, you'd get repeat employees wherever an employee belongs to more than one department. Though I don't believe it's necessary to do it in two steps:
@"departments.@distinctUnionOfSets.employees.@sum.salary" should do it.
精彩评论