NSOutlineView, reloading items, and the expansion state

Apple, Cocoa, Other Stuff

NSOutlineView requires all of the items in it to be pointer unique. If they are not, strange things happen. However, they can be equal (meaning [NSObject isEqual] may return YES).

However, there is a small exception to that rule. If you do a reload, the expansion state of items will be preserved. This expansion state is done by placing the current expanded items into an NSMutableSet. After a reload happens, if an item is in that set it is shown expanded.

What does this mean? Well, to see if an item should be expanded or not, it is looked up in the set. This is done via the item’s hashcode and an isEqual comparision. Ahh ha! NSOutlineView is doing some non-pointer unique things here. This means you could potentially switch out items during a reload, and they would still appear expanded after the reload (as long as they have the same hashcode and are isEqual). Another nasty side effect: any items which mutate their hashtable will not appear expanded after a reload! For instance, if you modify an NSDictionary, its hash code will change. Take this point into consideration: the objects you put into an NSOutlineView are NSMutableDictionaries. You do a reload, and after the reload you add a child to one of the items via a key in the NSDictionary. Therefore, the NSMutableDictionary now has a different hashcode, and it will no longer appear expanded! The easy way to work around this is to use a non-mutable object in the outlineview (such as your own object, which might have a dictionary inside of it to keep track of things). Just a neat tip, for those who care or run into this.

Previous Post
no_thumbnail
Burning man pictures and stuff
Next Post
no_thumbnail
Trials unicycling on “the machine” at burning man

6
Leave a Reply

avatar
500
6 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
4 Comment authors
georgeBonifaciuscorbinJerry Krinock Recent comment authors
  Subscribe  
Notify of
Jerry Krinock
Guest
Jerry Krinock

Thank you for explaining this.

Bonifacius
Guest

Great article. I am just sad I dont know how to reply properly, though, since I want to show my appreciation like many other.

george
Guest
george

I assume overriding isEqual: and hash: for the outline item class would be a Very Bad Ideaâ„¢ as it would screw up other things?

george
Guest
george

I was thinking specifically for a Core Data entity. I did a quick test and I’m still getting stray items collapsing. However, this is happening when I call rearrangeObjects on an NSTreeController to refresh the NSOutlineView so perhaps that’s a completely different case than what you’ve described for reloadData. I know Core Data + NSTreeController can complicate things quite a bit, so perhaps I’ll just end up saving expansion state in the model and restoring manually.

Thanks.

(c) 2008-2019 Corbin Dunn

Privacy Policy

Subscribe to RSS feeds for entries.

103 queries. 0.326 seconds.

Log in