reloadData в NSTableView, но сохранить текущий выбор
У меня естьNSTableView
показывая содержимое каталога. Я наблюдаю за FSEvents, и каждый раз, когда я получаю событие, я перезагружаю свое табличное представление. К сожалению, текущий выбор исчезает. Есть ли способ избежать этого?
5 ответов
Это зависит от того, как вы заполняете свой NSTableView.
Если у вас есть табличное представление, привязанное к NSArrayController, который, в свою очередь, содержит элементы, которые отображает ваше табличное представление, тогда NSArrayController имеет возможность сохранить выбор. Вы можете выбрать его (или нет) в Интерфейсном Разработчике как свойство NSArrayController. Или вы можете использовать setPreservesSelection
метод в коде.
Однако, если вы полностью замените массив элементов, которыми NSArrayController управляет каждый раз, когда вы получаете ваши FSEvents, то, возможно, сохранение выбора не сработает. К сожалению, документы Apple по этому свойству NSArrayController немного расплывчаты относительно того, когда он может и не может сохранить выбор.
Если вы не используете NSArrayController, но, возможно, используете источник данных для заполнения табличного представления, то я думаю, что вам придется управлять выбором самостоятельно.
Ну, вы можете сохранить выбор перед вызовом reloadData и восстановить его после этого.
NSInteger row = [self.tableView selectedRow];
[self.tableView reloadData];
[self.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
Это сработало для меня в некоторых случаях. Но если вы вставляете некоторые элементы ДО выбранной строки, вы должны просто настроить переменную строки, добавив к ней количество добавленных элементов.
Swift 4.2
Создайте расширение и добавьте метод, который сохраняет выбор.
extension NSTableView {
func reloadDataKeepingSelection() {
let selectedRowIndexes = self.selectedRowIndexes
self.reloadData()
self.selectRowIndexes(selectedRowIndexes, byExtendingSelection: true)
}
}
Делайте это в случае, если вы используете традиционный способ заполнения табличных представлений (не NSArrayController).
В случае использования источника данных документация Apple в заголовочном файле на reloadData()
в том, что
Выбранные строки не поддерживаются.
Чтобы обойти, вы можете использовать reloadDataForRowIndexes(rowIndexes: NSIndexSet, columnIndexes: NSIndexSet)
, Как уже упоминалось в том же заголовочном файле
Для видимых ячеек будут вызваны соответствующие методы dataSource и делегата, и ячейки будут перерисованы.
Таким образом, данные будут перезагружены, и выбор также сохранен.
Вариант ответа Сильванского.
Этот не нужно отслеживать количество элементов, вставленных / удаленных. И это поддерживает множественный выбор.
Идея состоит в том, чтобы...
1. создать массив выбранных объектов / узлов из текущего выбора.
2. обновить таблицу с помощью reloadData
3. для каждого объекта, полученного на шаге 1, найдите / запишите его новый индекс
4. скажите табличное представление / представление схемы, чтобы выбрать обновленный набор индекса
- (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];
}