xcode 如何在不使用 -reloadData 的情况下更新 NSTableView?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3977454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 19:51:27  来源:igfitidea点击:

How to update NSTableView without using -reloadData?

objective-ccocoaxcodemacosnstableview

提问by Omayr

I am new to the Mac. I am trying to update a particular cell in NSTableView without using -reloadData, as -reloadDataupdates the whole table. I have tried everything but all was in vain. I am trying to do something similar to what we used to do in CListCtrl in MFC or in .NET.

我是 Mac 新手。我试图在不使用-reloadData, 的情况下-reloadData更新NSTableView 中的特定单元格,因为更新整个表格。我已经尝试了一切,但一切都是徒劳的。我正在尝试做一些类似于我们过去在 MFC 或 .NET 中的 CListCtrl 中所做的事情。

回答by Vladimir

Have a look at reloadDataForRowIndexes:columnIndexes:method. To update a single cell the following should work:

看看reloadDataForRowIndexes:columnIndexes:方法。要更新单个单元格,以下应该起作用:

[yourTable reloadDataForRowIndexes:[NSIndexSet indexSetWithIndex:row]  
                     columnIndexes:[NSIndexSet indexSetWithIndex:column]];

回答by Chris Hanson

This is a fundamental difference between the way views typically work in Cocoa and how they work in some other frameworks. NSTableView does expose a -reloadDataForRowIndexes:columnIndexes:API, as Vladimir points out, but you'll notice the absence of a "withObject:" parameter.

这是视图在 Cocoa 中的典型工作方式与它们在其他一些框架中的工作方式之间的根本区别。-reloadDataForRowIndexes:columnIndexes:正如 Vladimir 指出的那样,NSTableView 确实公开了一个API,但您会注意到没有“withObject:”参数。

This is because Cocoa views and controls are notdesigned to also act as data containers. Rather, they're for presentation of and interaction with data that is managed by some other model object, usually through an intermediate controller of some sort.

这是因为 Cocoa 视图和控件并非设计为也充当数据容器。相反,它们用于呈现由其他模型对象管理的数据并与之交互,通常通过某种中间控制器。

Given a table view, for example, if your model has informed your controller that some particular data has changed, the controller can invalidate the displayed portion of the table that maps to that value - if there even isa displayed portion of the table. The next time it draws itself, the table will ask its data source (the controller) for the values to present for the area it needs to redraw.

例如,给定一个表视图,如果您的模型已通知您的控制器某些特定数据已更改,则控制器可以使映射到该值的表的显示部分无效 - 如果甚至表的显示部分。下一次它自己绘制时,表格会询问它的数据源(控制器)为它需要重绘的区域提供值。

Thus despite a superficial similarity in user interaction, you'll probably want to reconsider how you write the code to implement your user interface. You'll wind up with much more factored Model-View-Controller style code in the end; the price is that you'll need to actually represent your model more thoroughly than you might have had to in frameworks that didn't require such a separation of concerns.

因此,尽管用户交互表面上有相似之处,但您可能需要重新考虑如何编写代码来实现用户界面。最后你会得到更多分解的模型-视图-控制器风格的代码;代价是您实际上需要比在不需要这种关注点分离的框架中更彻底地表示您的模型。

回答by A.Badger

A full example of using reloadDataForRowIndexes to update all rows but only a single column:

使用 reloadDataForRowIndexes 更新所有行但仅更新一列的完整示例:

int col = 2 ;
[self.myTable reloadDataForRowIndexes:
    [NSIndexSet indexSetWithIndexesInRange:
        NSMakeRange(0,self.myTable.numberOfRows)] 
    columnIndexes:
        [NSIndexSet indexSetWithIndex:col]
];

Or all columns for a single row:

或单行的所有列:

int row = 2 ;
[self.myTable reloadDataForRowIndexes:
    [NSIndexSet indexSetWithIndex:row]
columnIndexes:
    [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.myTable.numberOfColumns)]
];

回答by Stickley

If your table row is smart enough to update itself with a draw, you can do something like this. This ViewController method is responding to a NSNotification post by a source object that has updated itself.

如果您的表格行足够智能,可以通过平局更新自身,您可以执行以下操作。此 ViewController 方法正在响应已更新自身的源对象的 NSNotification 帖子。

Swift 4 code:

斯威夫特 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))
    }
}

回答by Amy Worrall

Usually, updating the whole table via reloadData:is the correct design pattern. Why are you averse to doing so? Is it for efficiency reasons, or are you relying on the table to save some state and reloading all the data interferes with that? The latter is usually a sign that you need to rethink your architecture.

通常,通过更新整个表reloadData:是正确的设计模式。你为什么反对这样做?是出于效率原因,还是您依靠表来保存某些状态并重新加载所有数据会干扰它?后者通常表明您需要重新考虑您的架构。