|Home » Learning Curve » Developers Workshop
An evil bug in 10.6. H/T to Brian W for hunting it down.
There's an evil bug in Mac OS X 10.6. Search for either _determineDropCandidateForDragInfo or _dataSourceIsItemExpandable and you'll see quite a few people have had issues. The bug Brian found is a bug that wasn't there before in 10.5 or earlier. It has to do with the code class NSOutlineView.
The matter has since been protected by ACP code but here at any rate is what's going on.
Wherever the user hovers with the cursor on a drag operation over an instance of NSOutlineView, the underlying Apple code must determine what is to be selected and what is to be expanded. Apple's code for NSOutlineView has two internal methods to handle this.
Things start happening as soon as the cursor enters the outline view. The public method draggingEntered gets called first and it in turn calls the private method _determineDropCandidateForDragInfo which in turn calls another private method, _dataSourceIsItemExpandable.
Starting with 10.6 it is possible for these internal methods to pass 'garbage values' onto each other and onto client code. The bug is readily observed by letting the cursor hover over the header area of a drop-enabled outline view.
_dataSourceIsItemExpandable for 10.6 seems to want to call a client method to determine whether an outline view is expandable, this despite the Apple code already having made the call. _determineDropCandidateForDragInfo can in other words fail at determining that there is a candidate for 'drag info', but starting with 10.6, that doesn't stop it from passing on garbage values to other internal methods such as _dataSourceIsItemExpandable. And _dataSourceIsItemExpandable doesn't seem to care too much about what it passes on any longer either. Coding practice at its worst.
The workaround is fortunately eminently accessible: make sure your code checks what it's sent from Apple's code. Good code normally checks anyway. But in this particular instance it might be assumed Apple would never send a bogus pointer in such a call. Such was the case for 10.5 and earlier but it's certainly not the case any longer.
The good programmers are working on the iPad and the iPhone these days.
Developers Workshop: The Evolution of Style