My last Cocoa post described a problem I encountered extending a Core Data tutorial by using bindings operators to aggregate a property of Core Data entities through a relationship. With a bit of grovelling through documentation and some help and guidance from Tim Isted I’ve managed to get it to work, sort of.
Given Department and Employee entities and a ‘employees/department’ relationship between them, I tried to bind a column in an NSTableView to employees.@sum.fte
to display the Full Time Equivalent staffing for each department. Alas, it was not to be and in this post I’ll explain [a little] why this is not the case, and one way [a dirty, filthy hack] to work around it.
The problem is caused by the way in which Core Data returns the collection of entities at the “other” end of a to-many relationship. Core Data, as you may already know, loads data from a backing store lazily, that is: only when it absolutely must (or is told to). This has a number of benefits from a whole-system point of view including reducing memory consumption, decreasing data staleness, etc., etc. Core Data does this using faulting: when a piece of data is needed that hasn’t been loaded yet, it generates a fault (this is a grossly simplified over generalisation). Ordinarily this isn’t a problem: if you’re using entities through a controller (that prepares it’s content) or, I suspect, through a one-to-one relationship then everything works transparently. It does become a problem in this case when you want to use the far end of a to-many relationship. Rather than return a NSArray
and NSSet
or some other standard collection class, the relationship returned an _NSFaultingMutableSet
a private-ish (not the underscore) class that implements most of the interface of an NSMutableSet
. The key word here is most.
Where NSMutableSet
, NSArray
, their subclasses, and assorted others allow the use of set and array operators, _NSFaultingMutableSet
apparently doesn’t. Or not those that depend on the objects in the collection – like @sum
.
The new problem then is to convert this _NSFaultingMutableSet
into something the widget can display. Looking at the binding inspector in Interface Builder, the most obvious option is that Value Transformer box. Thankfully, value transforms are reasonably simple, especially when they are one way. After you subclass NSValueTransformer
to do what you need, create an instance, and register it with a given name (I did it in [MyDocument init]
as suggested by Tim, how ever you do it, it probably needs to be done before the NIB is loaded). Then entering the name in the Value Transformer box in IB gets it called. A little bit of code using an NSEnumerator
to emulate @sum
and it now works:

Thanks to Tim Isted for his help, guidance, and sample code. Suggestions are welcome as to other, perhaps better, ways to get this to work.