我正在使用基于视图的NSTableView,其中一列显示日期,表格单元格视图使用共享的DateFormatter。
let view: NSTableCellView? = tableView.makeView(withIdentifier: column.identifier, owner: self) as! NSTableCellView?
let entry = (logController.arrangedObjects as! [LogEntry])[row]
switch column.identifier {
case columnDateKey:
view?.textField?.formatter = sharedDateFormatter
view?.textField?.objectValue = entry.date
应用程序具有用户首选项以选择日期格式和先前的代码
tableView.setNeedsDisplay(tableView.rect(ofColumn: tableView.column(withIdentifier: columnDateKey)))
将使用新的日期格式刷新列。
使用macOS Mojave,这不会发生。调查显示,虽然drawRect:被调用为底层TableView,但没有调用tableView(:viewFor:row :)来获取表格单元格视图的新值。调用tableView.reloadData(forRowIndexes:columnIndexes :)会导致调用tableView(:viewFor:row :),但显示不刷新(尽管它对tableView.reloadData()有效)。
重绘的任何外部原因,例如选择一行正确地单独更新该区域。我看到的另一件事是,使用长桌慢慢向上滚动最终会导致出现新格式,尽管现有单元格在返回之前滚动回过去很长时间后不会改变。这似乎可以推断,当只有附加格式化程序的配置发生更改时,存在不被视为已更改的缓存视图(尽管内容的值发生更改时)
随着Mojave的引入,这种行为发生了变化,我发现很难相信没有其他人报告它,所以我开始质疑我的原始代码。我错过了什么吗?
以下测试代码演示了此问题,不会为setNeedsDisplay的变体打印“查看请求”消息,并且仅为reloadData()重新绘制显示
styleButton是用于切换数字格式的复选框,而refreshButton是用于请求重绘的操作按钮
将值设置为随机值将导致预期的重绘行为
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var window: NSWindow!
@IBOutlet weak var table: NSTableView!
@IBOutlet weak var styleButton: NSButton!
@IBOutlet weak var refreshButton: NSButton!
@IBOutlet weak var testView: NSView!
let numberFormatter = NumberFormatter()
func applicationWillFinishLaunching(_ notification: Notification) {
numberFormatter.numberStyle = symbolButton.state == NSControl.StateValue.on ? NumberFormatter.Style.decimal : NumberFormatter.Style.none
}
@IBAction func refresh(sender: Any?) {
numberFormatter.numberStyle = styleButton.state == NSControl.StateValue.on ? NumberFormatter.Style.decimal : NumberFormatter.Style.none
table.setNeedsDisplay(table.rect(ofColumn: 0))
// table.needsDisplay = true
// table.reloadData(forRowIndexes: IndexSet(integersIn: 0..<table.numberOfRows), columnIndexes:[0])
// table.reloadData()
}
}
extension AppDelegate: NSTableViewDataSource {
func numberOfRows(in tableView: NSTableView) -> Int {
if tableView == table {
return 40
}
return 0
}
}
extension AppDelegate: NSTableViewDelegate {
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
print("View requested")
guard tableColumn != nil else {
return nil
}
let column = tableColumn!
if tableView == table {
let view: NSTableCellView? = tableView.makeView(withIdentifier: column.identifier, owner: self) as! NSTableCellView?
view?.textField?.formatter = numberFormatter
view?.textField?.objectValue = 123.456
return view
}
return nil
}
}
错误地依赖view.setNeedsDisplay来自动更新子视图。情况并非如此(虽然之前似乎已经开始工作了) - 请参阅Willeke上面的评论