gpt4 book ai didi

macos - NSTableView reloadData(forRowIndexes :columnIndexes:) breaks autolayout

转载 作者:行者123 更新时间:2023-12-02 01:39:08 24 4
gpt4 key购买 nike

我有一个 NSTableView,可以根据行的数据值在不同的单元格 View 中交换。当模型更改时,我重新加载表,表的委托(delegate)将为新数据提供正确的表单元格 View 。

表格的单元格 View 使用自动布局。所有单元格 View 最初都会正常加载。在模型更改后更新表时,根据是调用 reloadData() 还是 reloadData(forRowIndexes:columnIndexes),我会得到不同的结果。使用reloadData()时,单元格 View 被加载并且自动布局工作正常。如果我使用 reloadData(forRowIndexes:columnIndexes),自动布局会产生完全不同的意外结果。

我创建了一个示例项目来演示该问题。 Here是项目设置的图像,包括在表格单元格 View 上设置的约束。有两个行模板,一个具有蓝色 View (偶数行),一个具有绿色(奇数行),应跨越表格宽度(减去一点填充)。 Controller 提供单元 View :

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 行的数据并重新加载数据。初始 View 看起来像 this (交替的绿色和蓝色矩形)。如果您使用 reloadData(),它看起来像 this (第 1 行从蓝色变为绿色)。但是,如果您使用 reloadData(withRowIndexes:columnIndexes:),单元格 View 将缩小到 40 点宽,而其他单元格 View 则为 480 点宽。 Here's View 调试器的抓取显示单元格 View 的大小错误,并显示不明确的宽度约束(使用 reloadData() 时不会发生这种情况)。

文档提到行 View 可以与 reloadData(forRowIndexes:columnIndexes:) 一起重用,但不能与 reloadData() 一起使用,我已经验证了这一点。我想行 View 的重用是导致自动布局问题的原因,但我找不到任何联系。在 SO、AppKit 发行说明、WWDC 视频、Google 搜索或我的头撞 table 上什么也没找到。非常感谢您的帮助。

更新:这是 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()
}
}

最佳答案

我想我已经成功了。如果我在单元格返回之前调用 layoutSubtreeIfNeeded() (这样它的所有 subview (如动态文本)都已设置),那么它似乎可以工作。

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
//...

cell.layoutSubtreeIfNeeded()
return cell
}

希望对您有所帮助。

关于macos - NSTableView reloadData(forRowIndexes :columnIndexes:) breaks autolayout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51016445/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com