Dynamic Binding

NSTreeController Memory Leaks Data Source Objects

When recently working on the iMedia Browser, I’ve been struggling with a strange kind of memory leak: whenever I replaced a node in my data source that was bound to an NSTreeController memory consumption on my App went up significantly (up to 20 MB in that case). This was supposed to be a memory consumption invariant operation since that new node was identical to the old one!

After thoroughly digging into it and appointing Instruments to help me on this I was finally convinced that my code in fact was balanced in terms of reference counting. This problem was to be blamed on the other usual suspect: Apple. Thanks to the Allocations instrument I finally figured out:

The number of live nodes always increased by at least one after I triggered the node replacement operation if and only if the old node was the selected item in the tree before being replaced. Since the old node was properly released due to being removed from the array it was (solely) referenced from the only possible explanation was that the associated NSTreeController was still retaining it.

I know, it’s a widespread vice of looking for somebody else to blame instead of keeping your own backyard tidy, but a small test project I set up makes it rather obvious that NSTreeController (as of 10.7.2) is in fact to be held accountable for this leakage. Luckily, there is a simple workaround to the problem which is to programmatically deselect a node in the NSTreeController before replacing it.

If you are interested in the sweaty details find them here.