NSBrowser Not Usable with NSTreeController

It seemed so simple. Just create a tree using NSTreeNode objects, bind an NSTreeController to it, and bind an NSBrowser to the controller. See Below:

[treeController bind:@"contentArray" toObject:self withKeyPath:@"rootArray" options:nil];
[browser bind:@"content" toObject:treeController withKeyPath:@"arrangedObjects" options:nil];

[browser bind:@"contentValues" toObject:treeController withKeyPath:@"arrangedObjects.representedObject" options:nil];
NSLog(@"browser: %@", browser);

Alas it is not meant to be. The NSBrowser object will inevitable cause a crash by infinitely recursing like so:

...
#19 0x94c9d48d in -[NSView setKeyboardFocusRingNeedsDisplayInRect:]
#20 0x94db7d2c in -[NSScrollView setKeyboardFocusRingNeedsDisplayInRect:]
#21 0x94c2bb7e in -[NSScrollView setNeedsDisplayInRect:]
#22 0x94c9d48d in -[NSView setKeyboardFocusRingNeedsDisplayInRect:]
#23 0x94db7d2c in -[NSScrollView setKeyboardFocusRingNeedsDisplayInRect:]
#24 0x94c2bb7e in -[NSScrollView setNeedsDisplayInRect:]
#25 0x94c9d48d in -[NSView setKeyboardFocusRingNeedsDisplayInRect:]
#26 0x94db7d2c in -[NSScrollView setKeyboardFocusRingNeedsDisplayInRect:]
...

With typical #macdev diplomacy, I've been told that bindings are the devil and that I should pursue an alternative approach. This is difficult to swallow because most examples of new cocoa code use bindings.

I now plan to try using NSBrowser with a delegate as the data source.

I've filed a bug report with apple. No response as of yet.

Update:
It turns out that infinite recursion errors in Cocoa are a special class of error not necessarily caused by improper memory management. Often, the cause is the interaction of two gui compoments "bouncing" off of each other -- one calls a method in the other, which calls a method in the other ad infinitum. In my case the infinite recursion bug occurs only when all sides of an NSBrowser are flush with a containing NSWindow AND there are multiple columns of data currently being displayed.


Update Update:
I believe the problem now can be described more precisely as occurring only when the NSBrowser bottom right corner overlaps with the grab-triangle at the bottom right corner of the containing NSWindow. Not TOTALLY sure about that though.

A Well Formed Question Often Contains the Answer

Often I find that the process of composing a question to a mailing lists elicits solutions that I was unable to think of while thrashing around with the code. Thus, often as not, I end up hitting delete rather than send. I believe that the process of explaining the problem to others forces me to purify my understanding of the problem, removing distracting noise that may have been inhibiting me.

Rigorous Thought

Programming successfully takes a certain amount of self awareness.

I usually start out a programming session with a certain goal I would like to achieve. At the end of the session, I try to be mindful of how close I come to achieving that goal, and if I do not, why not? If the only answer I can come up with is that "I tried X and it didn't work," it is a sign that I lack understanding of the problem. It is absolutely important to know why I was not able to achieve my goal. It is all too easy for me to give up on an approach and try another with slightly less desirable results without fully understanding why my first attempt failed.

If a physicist forms a hypothesis that when a ball is let drop at a certain height it will fall and finds in fact that the ball goes up, it would mean the physicist is upside down and is unaware of that fact. Put another way, if I try something and it doesn't work as I expected it to, it means I don't fully understand my software, which should be deeply troubling.

While giving up on my original goal and taking a slightly different route can seem like making progress, the result will be a mass of code that I can't explain. If someone asks me why I did X instead of Y, I will have no answer. It is extremely important to be aware of what you don't know.

Nu Bindings Example

I'm currently learning Nu (and by proxy, Objective-C/Cocoa) by implementing an app. I've been spending a lot of time wrapping my brain around the concepts behind cocoa bindings the past few days and came upon a case in which I needed control over how objects were inserted into an array bound to an NSArrayController. I found a perfect example of how to implement the indexed accessor methods required in order to be able to catch an object before it gets inserted into an observed array. However, the example code is of course in Objective-C, not Nu. I tried to implement the accessor methods in my app as shown in the example Objective-C code, but ended up with a crashing app. After translating from Objective-C to Nu and ending up with a non-working result, there's always a niggling suspicion that I somehow translated incorrectly from the original Objective-C to Nu. Having failed at trying the quick and easy route, and not having any idea what was causing the crash, I decided to implement the complete example in Nu.

This approach indeed helped me make progress towards resolving my bindings issues. The Nu version of the ManualBindings project can be found here: http://loglibrary.com/bindtest.tar.gz.

It turns out that I was using the "id" type inappropriately as a substitute for "unsigned int" when returning the count of items in the bound array. Although "unsigned int" is not currently bridged, "int" seems to be working.

It is not fully functional -- for some reason validatePrice is not being called. Any help figuring out why would be greatly appreciated and would be a nice addition to the cannon of Nu example code.