简体   繁体   中英

NSTableView – select clicked row after editing was ended by clicking a different row

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?

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
}

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...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM