Sort Descriptors, NSTableView Bindings, and You

Tuesday, 2008-12-23; 03:13:45

So if you’re using an NSTableView, an NSArrayController or an NSDictionaryController, and bindings to link the two, here’s a problem you might run into.

In Interface Builder, you can set NSTableViews to have autosave names, which allow table views to automatically save and restore various “settings” about the table view, like the column positions, column widths, hidden columns, column sorting, etc. Just by virtue of giving the NSTableView an autosave name in Interface Builder, it should start saving and restoring all of these settings.

It was the column sorting that was giving me trouble. Column widths and column positions were being saved perfectly fine, but my column sorting was always being reset to a default value after each launch. This problem pissed me off for a day, and looking through various documentation didn’t help, because it suggested that sort descriptors should be autosaved and restored.

Other oddities with this problem is that it seemed that the NSTableView was saving the sort descriptors to my app’s plist preference file, but wasn’t restoring it. I tried binding the NSTableView’s sort descriptors to an NSUserDefaultsController, and even that didn’t work. I tried manually getting the preferences via an NSUserDefaults object, hoping to programatically set the NSTableView’s sort descriptors on launch. What was weird was that when I tried to retrieve the sort descriptor settings that were clearly saved to the preference file, the NSUserDefaults object was returning null values for that key.

I’ve seen a few posts about this, but no answers. Because the almighty Google indexes all, I thought I’d post my solution.

The issue is that your NSArrayController or NSDictionaryController also has sort descriptors, and these seem to take precedence over the NSTableView’s own sort descriptors. But these sort descriptors don’t get autosaved along with the NSTableView’s other settings. So while the NSTableView does seem to save the sort descriptors, it would seem that it attempts to restore them but then they get obliterated by your NS*Controller’s sort descriptors, which are reset to default values on every launch.

The solution here is to bind your NSArrayController’s (or NSDictionaryController’s) sort descriptors to an NSUserDefaultsController. Select your controller, switch to the bindings tab in the inspector, and then click the “Sort Descriptors” disclosure triangle under the “Controller Content Parameters” section.

Check the “Bind to:” box, and select “Shared User Defaults Controller”. (This will automatically create an NSUserDefaultsController instance in your nib.) Set the controller key to “values” and the model key path to the key you want to use in your prefs file (for example, “sortDescriptors” is fine). You’ll need an NSUnarchiveFromData value transformer, and you’ll also want to check the “Validates Immediately” box so that your sorting gets saved to prefs as soon as the user clicks a column heading to change the sort order.

Activating bindings for controller sort descriptors

You’ll also want to make sure that your NSTableColumns have sort keys and selectors. This is easily done in Interface Builder as well. Select each of your NSTableColumns in turn (the inspector should start with “Table Column” if your column is correctly selected), and switch to the Attributes tab. For “Sort Key”, you’ll want to enter the model key path to your column data (in my case, my bindings controller key for the column is “arrangedObjects” and the model key path is “value.entryTitle”, so I put “value.entryTitle” in for my sort key). For “Selector”, type in a method name that tells your program how to sort your NSTableView items (for example, “compare:” or “caseInsensitiveCompare:”). Do this for each table column.

Setting column sort keys and selectors for NSTableColumns

You should probably unbind your NSTableView’s sort descriptors as well, if you’ve left them bound from pulling out your hair trying to figure out this problem.

I’m not sure if I would classify this as a bug or not. Is there any time when you would want sort descriptors for both the NSTableView and the NS*Controller that’s providing the NSTableView with data? Otherwise, NSTableView’s sort descriptors bindings should probably be grayed out when its corresponding controller is connected.

In any case, hopefully this helps anybody else who comes across this problem.

Technological Supernova   Software Development   Older   Newer   Post a Comment