Как обновить NSTableView без использования -reloadData?
Я новичок в Mac. Я пытаюсь обновить конкретную ячейку в NSTableView без использования -reloadData
, как -reloadData
обновляет всю таблицу. Я перепробовал все, но все было напрасно. Я пытаюсь сделать что-то похожее на то, что мы делали в CListCtrl в MFC или.NET.
5 ответов
Посмотри на reloadDataForRowIndexes:columnIndexes:
метод. Для обновления одной ячейки должно работать следующее:
[yourTable reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:row]
columnIndexes:[NSIndexSet indexSetWithIndex:column]];
Это фундаментальное различие между тем, как представления обычно работают в Какао, и тем, как они работают в некоторых других средах. NSTableView выставляет -reloadDataForRowIndexes:columnIndexes:
API, как указывает Владимир, но вы заметите отсутствие параметра withObject:.
Это связано с тем, что представления и элементы управления Какао не предназначены для работы в качестве контейнеров данных. Скорее, они предназначены для представления и взаимодействия с данными, которыми управляет какой-либо другой объект модели, обычно через некоторый промежуточный контроллер.
Например, при наличии табличного представления, если ваша модель проинформировала контроллер о том, что некоторые конкретные данные изменились, контроллер может сделать недействительной отображаемую часть таблицы, которая соответствует этому значению - если даже есть отображаемая часть таблицы. В следующий раз, когда она отрисовывает себя, таблица запросит у своего источника данных (контроллера) значения, которые нужно представить для области, которую нужно перерисовать.
Таким образом, несмотря на внешнее сходство во взаимодействии с пользователем, вы, вероятно, захотите пересмотреть то, как вы пишете код для реализации вашего пользовательского интерфейса. В итоге вы получите гораздо более разборчивый код стиля Model-View-Controller; цена заключается в том, что вам нужно будет на самом деле представлять свою модель более тщательно, чем вы могли бы иметь в рамках, которые не требовали такого разделения интересов.
Полный пример использования reloadDataForRowIndexes для обновления всех строк, но только одного столбца:
int col = 2 ;
[self.myTable reloadDataForRowIndexes:
[NSIndexSet indexSetWithIndexesInRange:
NSMakeRange(0,self.myTable.numberOfRows)]
columnIndexes:
[NSIndexSet indexSetWithIndex:col]
];
Или все столбцы для одной строки:
int row = 2 ;
[self.myTable reloadDataForRowIndexes:
[NSIndexSet indexSetWithIndex:row]
columnIndexes:
[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.myTable.numberOfColumns)]
];
Если ваша строка таблицы достаточно умна, чтобы обновить себя с помощью рисования, вы можете сделать что-то вроде этого. Этот метод ViewController отвечает на сообщение NSNotification исходным объектом, который обновился сам.
Swift 4 код:
class ObjectChooserListViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
@IBOutlet weak var tableView: NSTableView!
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(objectUpdating(_:)), name: NSNotification.Name("ObjectUpdating"), object: nil)
// more stuff happening
}
@objc func objectUpdating(_ notification: NSNotification) {
guard let object = notification.object as? MyCoolObject else {return}
guard let row = ObjectManager.shared.getRow(of: object.id) else {return}
guard let cellView = tableView.view(atColumn: 0, row: row, makeIfNecessary: false) else {return}
cellView.draw(tableView.frameOfCell(atColumn: 0, row: row))
}
}
Как правило, обновление всей таблицы через reloadData:
это правильный шаблон дизайна. Почему вы против этого? Это из соображений эффективности или вы полагаетесь на таблицу, чтобы сохранить какое-то состояние и перезагрузить все данные, которые мешают этому? Последнее обычно является признаком того, что вам нужно переосмыслить свою архитектуру.