У меня есть NSTableView
, показывающий содержимое каталога. Я смотрю FSEvents, и каждый раз, когда я получаю событие, я перезагружаю свой табличный вид.
К сожалению, текущий выбор затем исчезает. Есть ли способ избежать этого?
ReloadData в NSTableView, но сохранить текущий выбор
Ответ 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, и ячейки будут перерисовываться.
Таким образом, данные будут перезагружены, а выбор сохранен.