Подтвердить что ты не робот

ReloadData в NSTableView, но сохранить текущий выбор

У меня есть NSTableView, показывающий содержимое каталога. Я смотрю FSEvents, и каждый раз, когда я получаю событие, я перезагружаю свой табличный вид. К сожалению, текущий выбор затем исчезает. Есть ли способ избежать этого?

4b9b3361

Ответ 1

Это зависит от того, как вы заполняете свой NSTableView.

Если у вас есть представление таблицы, связанное с NSArrayController, которое, в свою очередь, содержит элементы, отображаемые в вашем представлении таблицы, тогда NSArrayController имеет возможность сохранить выбор. Вы можете выбрать его (или нет) изнутри Interface Builder в качестве свойства в NSArrayController. Или вы можете использовать метод setPreservesSelection в коде.

Однако, если вы полностью замените массив элементов, которым NSArrayController управляет каждый раз, когда вы получаете свои FSEvents, возможно, сохранение выбора не может работать. К сожалению, документы Apple по этому свойству NSArrayController немного расплывчаты относительно того, когда он может и не может сохранить выбор.

Если вы не используете NSArrayController, но, возможно, используя dataSource для заполнения табличного представления, я думаю, вам придется самостоятельно управлять выбором.

Ответ 2

Ну, вы можете сохранить выделение перед вызовом reloadData и восстановить его после этого.

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

В некоторых случаях это работало для меня. Но если вы вставляете некоторые элементы перед выбранной строкой, вы должны и просто изменить свою переменную строки, добавив к ней количество добавленных элементов.

Ответ 3

[Swift 3]

Создайте расширение и добавьте метод, который сохраняет выбор.

extension NSTableView {

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

Сделайте это, если вы используете традиционный способ заполнения табличных представлений (а не NSArrayController).

Ответ 4

Вариант ответа @silvansky.

У этого нет необходимости отслеживать количество вставленных/удаленных элементов. И он поддерживает множественный выбор.

Идея состоит в том, чтобы... 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];
}

Ответ 5

В случае использования источника данных документация Apple в файле заголовка на reloadData() заключается в том, что

Выбранные строки не поддерживаются.

Чтобы обойти, вы можете использовать reloadDataForRowIndexes(rowIndexes: NSIndexSet, columnIndexes: NSIndexSet). Как упоминалось в том же заголовочном файле

Для видимых ячеек будут вызываться соответствующие методы dataSource и delegate, и ячейки будут перерисовываться.

Таким образом, данные будут перезагружены, а выбор сохранен.