我正在使用基于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不会发生这种情况。调查显示,尽管为底层TableView调用了drawRect:,但没有对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
}
}
答案 0 :(得分:0)
错误地依赖view.setNeedsDisplay来自动更新子视图。事实并非如此(尽管以前似乎是这样工作的)-请参阅上面Willeke的评论