我有一个NSTableView,可以根据行的数据值在不同的单元格视图中交换。当模型更改时,我将重新加载表,表的委托将为新数据提供正确的表单元格视图。
该表将自动布局用于其单元格视图。最初,所有单元格视图均正常加载。在更改模型后更新表时,根据调用reloadData()
还是reloadData(forRowIndexes:columnIndexes)
的不同,结果会有所不同。使用reloadData()
时,将加载单元格视图,并且自动布局可以正常工作。如果使用reloadData(forRowIndexes:columnIndexes)
,则自动布局会产生完全不同的意外结果。
我创建了一个示例项目来演示该问题。 Here是项目设置的图像,包括在表格单元格视图上设置的约束。有两行模板,一个具有蓝图(偶数行),一个具有绿色(奇数行),它们应跨表宽度(减去一些填充)。控制器提供单元格视图:
class TableController: NSObject {
@IBOutlet weak var tableView: NSTableView!
var colorData = [1, 0, 1, 0]
@IBAction func swapLine(_ sender: Any) {
colorData[1] = (colorData[1] + 1) % 2
// tableView.reloadData()
tableView.reloadData(forRowIndexes: [1], columnIndexes: [0])
}
}
extension TableController: NSTableViewDataSource {
func numberOfRows(in tableView: NSTableView) -> Int {
return colorData.count
}
}
extension TableController: NSTableViewDelegate {
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let cellId = (colorData[row]) % 2 == 0 ? "EvenCell" : "OddCell"
return tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(cellId), owner: self)
}
}
界面中的按钮仅交换第1行的数据并重新加载数据。初始视图看起来像this(交替显示绿色和蓝色矩形)。如果使用reloadData()
,则看起来像this(第1行从蓝色更改为绿色)。但是,如果使用reloadData(withRowIndexes:columnIndexes:)
,则像其他单元格一样,单元格视图缩小到40点宽,反之为480。 Here's的视图调试器抓取,显示了具有错误尺寸的单元格视图并显示了不明确的宽度约束(使用reloadData()
时不会发生这种情况)。
文档中提到行视图已与reloadData(forRowIndexes:columnIndexes:)
一起使用,但没有与reloadData()
一起使用,我已经验证过。我想这种对行视图的重用是导致自动布局问题的原因,但是我找不到任何连接。在SO,AppKit发行说明,WWDC视频,Google搜索中找不到任何东西,或者从桌上砸了东西。衷心感谢您的协助。
更新: 这是ColorView的代码:
class ColorView: NSView {
@IBInspectable var intrinsicHeight: CGFloat = 20
@IBInspectable var color: NSColor = NSColor.blue
override var intrinsicContentSize: NSSize {
return NSSize(width: NSView.noIntrinsicMetric, height: intrinsicHeight)
}
override func draw(_ dirtyRect: NSRect) {
color.setFill()
dirtyRect.fill()
}
}
答案 0 :(得分:0)
我认为我已经做好了。如果我在返回之前在单元格上调用layoutSubtreeIfNeeded()
(这样就已经设置了它的所有子视图(如动态文本)),那么它似乎可以工作。
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
//...
cell.layoutSubtreeIfNeeded()
return cell
}
我希望有帮助。
答案 1 :(得分:0)
我遇到了同样的问题,并注意到对于需要reloadData
的行,缺少实际的自动布局约束。我(骇人听闻的)解决方案是添加应该手动为单元自动设置的约束。请注意,在表格视图中,我只使用一列,因此我可以将宽度约束设置为等于行的宽度,而不必依赖于指定的列宽度。
class CustomRowView: NSTableRowView {
override func addSubview(_ view: NSView) {
super.addSubview(view)
// Add constraints NSTableView is supposed to set up
view.topAnchor.constraint(equalTo: topAnchor).isActive = true
view.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 1.0).isActive = true
view.layoutSubtreeIfNeeded()
}
}