0

I have an NSBrowser which displays 2 columns of data that is calculated on several other threads while my app is running. The problem I'm trying to solve is to allow the user to interact with the browser while the data is still coming in. Right now, when a background thread indicates there are new rows to be displayed, I call -[NSBrowser reloadColumn:0]. This works when the user is simply looking at data in column 0. However, if they attempt to select an item in column 0, it will immediately become deselected as soon as the app calls reloadColumn:0. The data often comes in as hundreds of rows per second.

As a workaround, I tried getting the current selection before calling reloadColumn:0 and then resetting it immediately afterwards. This keeps the selection as desired, but if the user scrolls the selection off the view, as soon as the column is reloaded, the scroll position pops back to including the selected row. Trying to use the selectionIndexPath property has the same effect.

So it appears that I have to choose between:

  1. The user's selection will disappear every few seconds
  2. The user won't be allowed to scroll the selection off the screen

Neither of these are very useable. I have also tried calling -[NSBrowser reloadDataForRowIndexes:inColumn: to only "reload" (or actually load) the new rows, but this does not load rows which were not already loaded, apparently. Basically, after loading the first row, no further rows show up.

I also tried calling -loadedCellAtRow:Column: on every newly created row, and it also does not cause anything that wasn't previously loaded to load.

Is there a way to get this to work that won't annoy the user?

For what it's worth, I've implemented the following NSBrowserDelegate methods in my app:

- (BOOL)browser:(NSBrowser *)browser isColumnValid:(NSInteger)column
- (NSString*)browser:(NSBrowser *)sender titleOfColumn:(NSInteger)column
- (void)browser:(NSBrowser *)browser willDisplayCell:(nonnull id)cell atRow:(NSInteger)row column:(NSInteger)column
- (NSInteger)browser:(NSBrowser *)sender numberOfRowsInColumn:(NSInteger)column
- (NSInteger)browser:(NSBrowser *)browser numberOfChildrenOfItem:(id)item;
- (id)browser:(NSBrowser *)browser child:(NSInteger)index ofItem:(id)item;
- (id)browser:(NSBrowser *)browser objectValueForItem:(id)item;
- (id)rootItemForBrowser:(NSBrowser *)browser;
- (BOOL)browser:(NSBrowser *)browser isLeafItem:(id)item

If it would make sense to implement other delegate methods to clear this up, I'd be interested in knowing that.

user1118321
  • 25,567
  • 4
  • 55
  • 86
  • How do you get and set the selection? Did you try other selection methods? – Willeke Aug 26 '18 at 23:38
  • I'm calling `-[NSBrowser selectedRowInColumn:0]` to get the selection and `-[NSBrowser selectRow:inColumn:]`. Other than `-selectAll`, I don't see any other way to set the selection. – user1118321 Aug 27 '18 at 00:26
  • Try getting and setting property `selectionIndexPath` or `selectionIndexPaths`. – Willeke Aug 27 '18 at 10:13
  • Just tried it and unfortunately, I get the same result. – user1118321 Aug 28 '18 at 02:00
  • I tried `selectionIndexPaths` in a small test app and it doesn't scroll. Which methods do you use to provide the data? What are the settings of the browser? – Willeke Aug 28 '18 at 12:05
  • I've added the info above. – user1118321 Aug 29 '18 at 06:02
  • I tried to reproduce (and fix) the issue. Attempt 1: when I add an item the first item is selected, fixed by getting and setting `selectionIndexPaths`, doesn't scroll. Attempt 2: implemented `isColumnValid` and `titleOfColumn`, the selection is scrolled into view. Attempt 3: several failed experiments to fix the issue. Attempt 4: removed all fixes, the selected item stays selected, no scrolling, can't reproduce the issue anymore. Weird. – Willeke Aug 29 '18 at 20:29
  • Well thanks for trying! I guess I should file a bug about it. – user1118321 Aug 30 '18 at 02:34
  • Or find out why the selection doesn't stick. `reloadColumn:0` tries to reselect the same objects. – Willeke Aug 30 '18 at 06:22

0 Answers0