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

时间:2010-10-20 11:52:14

标签: objective-c cocoa xcode macos nstableview

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

5 个答案:

答案 0 :(得分:29)

查看reloadDataForRowIndexes:columnIndexes:方法。要更新单个单元格,以下内容应该有效:

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

答案 1 :(得分:19)

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

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

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

因此,尽管用户交互存在表面上的相似性,但您可能希望重新考虑如何编写代码来实现用户界面。最后,您将了解更多因素模型 - 视图 - 控制器样式代码;价格是你需要比在不需要分离关注点的框架中更彻底地代表你的模型。

答案 2 :(得分:2)

使用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)]
];

答案 3 :(得分:0)

如果表行足够聪明,可以通过抽奖来更新自身,则可以执行以下操作。此ViewController方法通过已更新自身的源对象来响应NSNotification帖子。

快速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))
    }
}

答案 4 :(得分:-5)

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