On Jul 10, 2014, at 4:20 PM, Bill Cheeseman <wjcheese...@gmail.com> 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 - b...@cheeseman.name

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to