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];
}
Другие вопросы по тегам