Skip to end of metadata
Go to start of metadata

Have you ever used a rule qualifier like "object.employees.count > 0" in Wonder?  Object is whatever your current object happens to be, employees is a to many relationship off of object, and count is the count method on NSArray. Simple enough, right?

Have you ever tried "object.employees.isEmpty = 1" instead?  It doesn't work. You might wonder, why not??  count() is just a method on NSArray.  isEmpty() is as well.  Why does one work and one fail?  This has to do with how valueForKey is evaluated on NSArray.

With NSArray, when you call valueForKey, you call it on the array's objects instead of the array itself. So, when your qualifier key path is evaluated, anything after "object.employees." is evaluated on the objects inside the array. For example calling valueForKeyPath using "object.employees.salary" will produce an array of salaries rather than trying to call the method salary() on NSArray.  But wait! That means that instead of calling count on the array, count should be called on the objects instead.  So why isn't count failing just like isEmpty??

The answer lies in the Wonder NSArray implementation.  If you look at the source for the valueForKey method on Wonder's reimplemented NSArray, you'll see the answer.  The first thing valueForKey does is examine the key when it is non-null.  If the key begins with the operator character @, then it executes the key as an NSArray operator.  After that, it checks one more thing... is the key "count".  If so, it returns the array's count() method.

And with this information, we now have a solution to our problem. It turns out that Wonder provides us with an isEmpty array operator. So if you want to use the isEmpty method in a qualifier key path, you would use "object.employees.@isEmpty" instead.

This is great news, because if I understand Wonder's rule system caching correctly, object.employees.count will cache a new value every time the keypath evaluates to a new count.  With isEmpty, there are only two possible values to cache and compare. So using isEmpty for keyPaths beginning with "object" or "session" should result in faster comparison and a smaller memory footprint too :)