Re: Issue with -[NSOutlineView autosaveExpandedItems] - SOLVED
Re: Issue with -[NSOutlineView autosaveExpandedItems] - SOLVED
- Subject: Re: Issue with -[NSOutlineView autosaveExpandedItems] - SOLVED
- From: Bill Cheeseman <email@hidden>
- Date: Fri, 11 Jul 2014 08:35:50 -0400
On Jul 10, 2014, at 4:20 PM, Bill Cheeseman <email@hidden> wrote:
> How can I make an outline view reinstate the expanded and collapsed state of its rows across application launches?
I finally realized that older code in my -awakeFromNib method was undoing everything that the datasource method -outlineView:itemForPersistentObject: was doing at application launch. NSLog calls showed me that the datasource method is called at launch BEFORE -awakeFromNib is called. Because I had been populating my datasource and expanding all rows in -awakeFromNib, I was canceling out what the datasource method had done. I would guess that most developers do this in -awakeFromNib, just as I did, because that's how Apple's sample projects do it. I haven't found any sample projects that use these datasource methods, so it didn't matter until I started trying to work them into my project.
As soon as I moved the code that populates the datasource into my view controller's designated initializer, and removed that code and the code that expanded the entire outline from -awakeFromNib, everything started working correctly.
So here are the basic requirements for setting up autosaveExpandedItems in an outline view:
1. Set autosaveExpandedItems in the outline view nib file or by calling -setAutosaveExpandedItems:YES. (And NSTableView's autosaveName must also be set, which is well documented.)
2. Implement the outline view datasource methods -outlineView:itemForPersistentObject: and -outlineView:objectForPersistentItem: by returning the results from -[NSKeyedArchiver archiveDataWithRootObject:] and -[NSKeyedUnarchiver unarchiveObjectWithData:]. In these methods, it is only necessary to archive the datasource item passed in to -outlineView:objectForPersistentItem:; no other processing is required. AppKit calls this datasource method at the moment you expand or collapse any row in the outline view, adding the archived item to user defaults when you expand it and removing it from user defaults when you collapse it. The autosave user defaults entry is an array of NSData objects constituting the archived datasource items for expanded rows only. The user defaults entry is named "NSOutlineView Items <autosave name>". When you quit and later relaunch the application, AppKit calls -outlineView:itemForPersistentObject: once for each NSData object in the user defaults autosave entry. It does this before -awakeFromNib, so your datasource must be populated before that (e.g., in the designated initializer) or nothing will happen. Apparently (just guessing here) AppKit compares or subsitutes the unarchived user defaults objects with the datasource contents and expands any and all rows that match. Object-equality only is required, not pointer-identity, because AppKit can handle that issue behind the scenes whether it uses comparison or substitution. (It would seem that you could archive UUIDs or any other kind of unique identifier instead of the datasource item itself in -outlineView:objectForPersistentItem:, as long as you find or reconstruct the datasource item itself and return it in -outlineView:itemForPersistentObject:. This would be the way to go in a Core Data application.)
3. Populate the outline view's datasource in the controller's designated initializer.
4. In -awakeFromNib or equivalent, set up the initial expanded/collapsed state of rows in the outline view only once, at first launch on a given computer. Thereafter, leave it to the datasource methods to expand or collapse the outline view at launch based on the autosaved information from a previous run.
So simple. Too bad the reference document doesn't spell this out a little more clearly. (The problem faced by documentation writers is that, if they're any good, they know too much and it all seems perfectly obvious.)
--
Bill Cheeseman - email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden