Reputation: 1675
I have an NSTableView
which gets populated without bindings.
In the datasource method tableView:objectValueForTableColumn:row:
, I re-sort my data and tell the table view to reload after committing the edit to the model, so that the correct sort order is restored after editing.
If the user ends editing by clicking a different row, however, and the sort order has changed because of the edit that has just been ended, it might happen that the row the user intended to select has just moved after he clicked it. So instead of that row, a different row that is now in that spot gets selected.
I tried various combinations of the NSTableViewDelegate
methods, but could not find a solution that adjusts the selection in a way that when a re-sort after editing has ended has occurred, the row that has just moved away gets selected. How can I achieve this?
Upvotes: 4
Views: 1478
Reputation: 7191
I would use this:
I recommend to sort
your data in NSTableView delegate setObjectValue:
instead of objectValueForTableColumn:
And change the selection in NSTableView delegate selectionIndexesForProposedSelection:
This solution manages a single selection, If you want it manages single and multiple selection, I would change my answer. If the user double-click, it doesn't work since it changes the selection to the second click.
You need these variables :
int originalRowIndex;
NSUInteger newRowIndex;
I initialize this variable: originalRowIndex = -1;
- (void)tableView:(NSTableView *)aTable setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aColumn row:(int)rowIndex {
id objectAtRow = [myMutableArray objectAtIndex:rowIndex];
NSString *columnKey = [aColumn identifier];
[objectAtRow setValue:anObject forKey:columnKey];
originalRowIndex = rowIndex; // get the original index
[myMutableArray sortUsingDescriptors:[aTable sortDescriptors]]; // re-sort the mutable array
newRowIndex = [myMutableArray indexOfObjectIdenticalTo:objectAtRow]; // get the new index
if (newRowIndex == originalRowIndex) originalRowIndex = -1; // same position
}
// not called on empty selection
- (NSIndexSet *)tableView:(NSTableView *)tableView selectionIndexesForProposedSelection:(NSIndexSet *)proposedSelectionIndexes {
int oIndex = originalRowIndex;
originalRowIndex = -1;
if (oIndex > -1 && [proposedSelectionIndexes count] > 1) { // if oIndex = -1 or multi selection , do nothing
int i = [proposedSelectionIndexes firstIndex];
if (oIndex < newRowIndex) {
if (i > oIndex && i <= newRowIndex) return [NSIndexSet indexSetWithIndex:(i - 1)];//shift the row index
} else {
if (i < oIndex && i >= newRowIndex) return [NSIndexSet indexSetWithIndex:(i + 1)];//shift the row index
} //else doesn't change the selection, this index is out of range (originalIndex...newIndex)
}
return proposedSelectionIndexes;// doesn't change the selection
}
Upvotes: 3
Reputation: 12496
I've always done this the hard way: before doing something that needs the selection to be restored, I remember the current selection -- not by row index, but by something I can find in my data. Often I have an array of dictionaries, so I just remember the dictionary pointer.
After doing whatever I need to do on the tableview, I just go through the data again, looking for my object to find the new index...
Upvotes: 2