objective-c cocoa macos nstableview fsevents

objective c - reloadData en NSTableView pero mantiene la selección actual



objective-c cocoa (5)

Tengo un NSTableView muestra los contenidos de un directorio. Observo los eventos FSE, y cada vez que obtengo un evento, vuelvo a cargar mi vista de tabla. Desafortunadamente, la selección actual desaparece. ¿Hay alguna manera de evitar eso?


Bueno, puede guardar la selección antes de llamar a reloadData y restaurarla después de eso.

NSInteger row = [self.tableView selectedRow]; [self.tableView reloadData]; [self.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];

Esto me funcionó en algunos casos. Pero si inserta algunos elementos ANTES de la fila seleccionada, debe y ajustar su variable de fila agregando un número de elementos agregados a ella.


Depende de cómo rellene su NSTableView.

Si tiene la vista de tabla vinculada a un NSArrayController, que a su vez contiene los elementos que muestra su vista de tabla, entonces NSArrayController tiene una opción para conservar la selección. Puede seleccionarlo (o no) dentro de Interface Builder como una propiedad en el NSArrayController. O puede usar el método setPreservesSelection en el código.

Sin embargo, si reemplaza completamente el conjunto de elementos que administra NSArrayController cada vez que obtiene sus eventos FSE, tal vez la conservación de la selección no funcione. Desafortunadamente, los documentos de Apple en esta propiedad de NSArrayController son un poco vagos en cuanto a cuándo puede y no puede preservar la selección.

Si no está utilizando un NSArrayController, pero tal vez esté utilizando una fuente de datos para completar la vista de tabla, creo que tendrá que administrar la selección usted mismo.


En el caso de usar Data Source, la documentación de Apple en el archivo de encabezado en reloadData() es la siguiente:

Las filas seleccionadas no se mantienen.

Para desplazarse, puede usar reloadDataForRowIndexes(rowIndexes: NSIndexSet, columnIndexes: NSIndexSet) . Como se menciona en el mismo archivo de cabecera

Para las celdas que están visibles, se invocarán los métodos de dataSource y delegate apropiados y las celdas se volverán a dibujar.

Por lo tanto, los datos se volverán a cargar y la selección también se mantendrá.


Una variante de la respuesta de @silvansky.

Este no tiene necesidad de realizar un seguimiento del recuento de elementos insertados / eliminados. Y mantiene la selección múltiple.

La idea es ...
1. cree una matriz de objetos / nodos seleccionados de la selección actual.
2. actualizar la tabla utilizando reloadData
3. para cada objeto obtenido en el paso 1, busque / registre su nuevo índice
4. indique a la vista de tabla / vista de esquema que seleccione el conjunto de índices actualizado

- (void)refresh { // initialize some variables NSIndexSet *selectedIndexes = [self.outlineView selectedRowIndexes]; NSMutableArray *selectedNodes = [NSMutableArray array]; NSMutableIndexSet *updatedSelectedIndex = [NSMutableIndexSet indexSet]; // 1. enumerate all selected indexes and record the nodes/objects [selectedIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { [selectedNodes addObject:[self.outlineView itemAtRow:idx]]; }]; // 2. refresh the table which may add new objects/nodes [self.outlineView reloadData]; // 3. for each node in step 1, find the new indexes for (id selectedNode in selectedNodes) { [updatedSelectedIndex addIndex:[self.outlineView rowForItem:selectedNode]]; } // 4. tell the outline view to select the updated index set [self.outlineView selectRowIndexes:updatedSelectedIndex byExtendingSelection:NO]; }


Swift 4.2

Crea una extensión y agrega un método que conserve la selección.

extension NSTableView { func reloadDataKeepingSelection() { let selectedRowIndexes = self.selectedRowIndexes self.reloadData() self.selectRowIndexes(selectedRowIndexes, byExtendingSelection: true) } }

Haga esto en caso de que utilice la forma tradicional de rellenar vistas de tabla (no NSArrayController).