Re: NSTableView: programatically changing sorted column
Re: NSTableView: programatically changing sorted column
- Subject: Re: NSTableView: programatically changing sorted column
- From: Graham Cox <email@hidden>
- Date: Tue, 6 Jul 2010 13:40:46 +1000
Hi Scott,
Yes I'm implementing the delegate method. Sorting is working just fine: when I click the column headers sort descriptors are updated, the delegate is informed, the controller does its thing with the data and all is well.
The issue is when I try to accomplish this programatically (from a menu, in fact).
If I call [NSTableView setHighlightedColumn:], the sort descriptors are not changed and the delegate is not informed (even though the UI now appears to indicate a different sorted column).
If I call [NSTableView setSortDescriptors:] the column highlight is not changed though the delegate IS informed (and again, the table view order does not match the highlighted column - in fact the sorting indicator does update for the right column but the blue highlight is elsewhere).
Because of this programmatic disconnect between these two methods (which may well be intentional though I don't quite see the logic of it, and maybe that's where the documentation could be clarified), I have to duplicate the work that NSTableView does to change its internal sort descriptors. At the very least there ought to be an entry point to do that.
So far I'm getting the delegate method to search for the column having a sort descriptor with a matching key and calling -setHighlightColumn: with that column. That takes care of highlighting the column to match the sort descriptor. The other part is the code which reorders the array of sort descriptors to match what I want. I've got that part working now by searching on the descriptor's key rather than assuming that the prototype gets copied to the array as is, i.e:
NSTableColumn* column = [mItemsListView tableColumnWithIdentifier:columnIdentifier];
if( column && !(column == [mItemsListView highlightedTableColumn]))
{
NSSortDescriptor* sd = [column sortDescriptorPrototype];
if( reverse )
sd = [sd reversedSortDescriptor];
// just switching the column isn't enough - the sort descriptors must be updated ourselves
// (grr, why doesn't the table view do this?)
NSMutableArray* sortDescs = [[mItemsListView sortDescriptors] mutableCopy];
// remove all sort descriptors having the same key
NSEnumerator* iter = [[mItemsListView sortDescriptors] objectEnumerator];
NSSortDescriptor* desc;
while(( desc = [iter nextObject]))
{
if([[desc key] isEqualToString:[sd key]])
[sortDescs removeObject:desc];
}
[sortDescs insertObject:sd atIndex:0];
// setSortDescriptors informs the delegate (self) which updates the highlighted column
[mItemsListView setSortDescriptors:sortDescs];
[sortDescs release];
}
and my delegate method:
- (void) tableView:(NSTableView*) aTableView sortDescriptorsDidChange:(NSArray*) oldDescriptors
{
// pass this on to the next level controller which performs the actual sort and reload
if([[self delegate] respondsToSelector:@selector(sortDescriptorsChanged:)])
[[self delegate] sortDescriptorsChanged:oldDescriptors];
// keep the highlighted column in synch (workaround for odd behaviour with programmatic sorting)
NSSortDescriptor* sd = [[aTableView sortDescriptors] objectAtIndex:0];
if( sd )
{
NSEnumerator* iter = [[aTableView tableColumns] objectEnumerator];
NSTableColumn* column;
while(( column = [iter nextObject]))
{
if([[[column sortDescriptorPrototype] key] isEqualToString:[sd key]])
{
[aTableView setHighlightedTableColumn:column];
break;
}
}
}
}
On 06/07/2010, at 1:15 PM, Scott Anguish wrote:
> are you implementing the delegate method?
>
>
> - (void)tableView:(NSTableView *)tableView sortDescriptorsDidChange:(NSArray *)oldDescriptors
> {
> // the sort descriptors are specified in Interface Builder for the lastName column and the relationship column
> // the both specify the respective keys, and use the compare: method to do the sorting
> // this message is sent to the delegate when the data is sorted by clicking on one of those column headers
> [peopleArray sortUsingDescriptors: [tableView sortDescriptors]];
> [tableView reloadData];
> }
>
>
> I’m setting the sort information in Interface Builder on each column, specifying the key to sort on, and the compare selector (which is compare: which probably isn’t the best for localized content). I agree that both the hidden and non-hidden columns should have the same key and compare selector for both columns.
>
> When you click on one of those table column headers, the delegate is notified.
>
> Now, this does ‘destroy’ the natural sort order. But you can easily copy that natural order array into a ‘displayed’ array when loaded, and then upon some action, put a copy of that natural array in the displayed array. The delegate implementation above would do something like
>
> self.displayArray=[naturalOrderArray sortedArrayUsingDescriptors:[tableview sortDescriptors]];
>
> Is this helpful? If you’re having sorted issues that need documenting file a bug and send me the number ASAP. Seriously, ASAP.
_______________________________________________
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