5

I'm working on window restoration in a non-document-based Cocoa app. The app has a Mail.app-like interface. Each window represents an account; a sidebar in that window lists conversations in that account, and a main area lists messages in the selected conversation.

Each of these lists is a view-based NSTableView. The conversation list is bound to an NSArrayController whose contentSet is bound to the window controller's account property; the message list is bound to a second NSArrayController, whose contentSet is bound to the first NSArrayController's selection.

I've gotten my window restoration work to the point where it re-opens all the windows and re-associates them with the account objects, but I don't know how to restore the selections of the table views. This doesn't seem to happen automatically—when the window is restored, an object is selected, but it's not the one that was previously selected. What's going on here? What will be the easiest approach to saving and restoring the selection?

Becca Royal-Gordon
  • 17,541
  • 7
  • 56
  • 91

1 Answers1

5

As you realized, NSTableView doesn't auto save the selection.

The easiest way is to bind your NSTableView's selectionIndexes to your Array Controller's selectionIndexes, and save/retrieve values from NSUserDefaults. Then you can bind the array controller's selectionIndexes to the Shared User Defaults Controller (with Controller Key values and you can name your Model Key Path anything). Because NSIndexSet needs to be archived/unarchived to be stored, use the NSKeyedUnarchiveFromData value transformer. That, in itself, should work.


If you had trouble like I did with the selection indexes resetting because the table view wasn't immediately repopulated (I doubt you'd have these problems, because you're populating with bindings), you can save defaults manually.

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:[NSKeyedArchiver archivedDataWithRootObject:self.arrayController.selectionIndexes] valueForKey:vvLastSavedSelectionIndex];

And retrieve them:

NSIndexSet *selectionIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] valueForKey:vvLastSavedSelectionIndex]];
[self.arrayController setSelectionIndexes:selectionIndexes];
Vervious
  • 5,559
  • 3
  • 38
  • 57
  • Since I can have multiple windows and I'm already using `NSWindowRestoration`, I encoded them into the window's restorable state using the `-window:willEncodeRestorableState:` and `-window:didDecodeRestorableState:` delegate methods, but that was definitely a good approach. Thanks! – Becca Royal-Gordon Aug 09 '12 at 05:25
  • @BrentRoyal-Gordon That definitely sounds alot smoother than writing to `NSUserDefaults` in the case of multiple windows (and even one window), thanks for letting me know about your method! – Vervious Aug 09 '12 at 05:57
  • Somehow, when I do exactly that (EVEN with the code, but I have bindings), the TableView is instantly empty :( I'm talking about Vervious' idea, because my app isn't Document-based. Any idea? – StuFF mc Nov 22 '12 at 16:58