NSTableView updating

I have an NSTableView which shows the longitude and latitude points of objects on a map. Some objects, like trails, have many rows in the table. When I change objects I want to update the NSTableView and then select row 0. I tried

[obectCoordTable reloadData];

[objectCoordTable selectRowIndexes: [NSIndexSet indexSetWithIndex: 0] byExtendingSelection: NO];


This does not work because reloadData does not reload the table. It only schedules a reload for some time later

(on next iteration of Main Loop?). So my attempt to select row 0 happens first. Then just before the table

data are reloaded a (void)tableViewSelectionDidChange: happens with selected row reset to -1. So my

selection of row 0 is ineffective.


How do I select row 0 after the reload is finished? There seems to be no delegate method to notify the user

when a complete data reload is completed.


Do I have to schedule the selectRowIndexes for execution at a later time and hope it is after the data reload? That might work but seems a bit too hokey?


Thanks.


Richard Stover

Accepted Reply

Unfortunately NSTableView does not respond to layoutIfNeeded. But your suggestion led me into looking

at other possibilities.


Instead of doing the selectRowIndexes: after the reloadData I set a BOOL flag, needsReselect.


Then in the delegate tableView:objectValueForTableColumn:row: method I put this code:

// If we are updating the table content at row 0 and we need to reset the selection to row 0

// then do that now.   

if ((rowIndex == 0) && needsReselect) {


          // Select row 0.

          [objectCoordTable selectRowIndexes: [NSIndexSet indexSetWithIndex: 0] byExtendingSelection: NO];


          // Get the rectangle for the table contents.

          CGRect r = objectCoordTable.superview.layer.contentsRect;


          // Narrow the rect to an area that is part of row 0.

          NSRect row0 = NSMakeRect(0.0, r.size.height - 10.0, r.size.width, 5.0);


          // Scroll to that rect

          [objectCoordTable.superview scrollRectToVisible:row0];

          needsReselect = NO;

     }

This seems a little more obvious that using a dispatch queue and it seems to work. Note that I had to explicitly reset

the scroll as well. I checked, and if I'm not in the middle of the tableView:objectValueForTableColumn: the scoll

adjusts without need to control it explicitly.


It would be nice if there was a delegate method to mark the end of a reloadData, or an NSNotification about it.


Thanks for the help.

Replies

Do I have to schedule the selectRowIndexes for execution at a later time and hope it is after the data reload?

No. You need to have something deterministic.


A solution could be to force redraw, by foring layout for instance.

Or to put the index selection in a dispatch queue.


See discussion here (that's UIKit but will give hints).

https://stackoverflow.com/questions/16071503/how-to-tell-when-uitableview-has-completed-reloaddata

Unfortunately NSTableView does not respond to layoutIfNeeded. But your suggestion led me into looking

at other possibilities.


Instead of doing the selectRowIndexes: after the reloadData I set a BOOL flag, needsReselect.


Then in the delegate tableView:objectValueForTableColumn:row: method I put this code:

// If we are updating the table content at row 0 and we need to reset the selection to row 0

// then do that now.   

if ((rowIndex == 0) && needsReselect) {


          // Select row 0.

          [objectCoordTable selectRowIndexes: [NSIndexSet indexSetWithIndex: 0] byExtendingSelection: NO];


          // Get the rectangle for the table contents.

          CGRect r = objectCoordTable.superview.layer.contentsRect;


          // Narrow the rect to an area that is part of row 0.

          NSRect row0 = NSMakeRect(0.0, r.size.height - 10.0, r.size.width, 5.0);


          // Scroll to that rect

          [objectCoordTable.superview scrollRectToVisible:row0];

          needsReselect = NO;

     }

This seems a little more obvious that using a dispatch queue and it seems to work. Note that I had to explicitly reset

the scroll as well. I checked, and if I'm not in the middle of the tableView:objectValueForTableColumn: the scoll

adjusts without need to control it explicitly.


It would be nice if there was a delegate method to mark the end of a reloadData, or an NSNotification about it.


Thanks for the help.

Thanks for feedback. Don't forget to close the thread.