views:

384

answers:

2

I'm trying to get total salary for the whole company by:

NSNumber *totalSalary  = [company valueForKeyPath:@"[email protected]"];

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.

+2  A: 

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 [email protected][email protected] 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:

@"[email protected][email protected]" should do it.

Joshua Nozzi
I don't think @"[email protected][email protected]" will work. [email protected] is not a set, so you can't take the union of all such sets.
Barry Wark
I tried that, didn't work.
Seymour Cakes
+5  A: 

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:@"[email protected]"];
NSNumber *totalSalary = [allEmployees valueForKeyPath:@"@sum.salary"];

Assuming each employee is in only one department, the following also appears to work

NSNumber *totalSalary = [company valueForKeyPath:@"[email protected][email protected]"];
Barry Wark
hmm I didn't know we can use the debugger interactively, I always thought if we wanted that we could use Ruby Cocoa or PyObjC. But THanks!
Seymour Cakes