NSOutlineView - 获取给定项目的 NSTableCellView
NSOutlineView - Get NSTableCellView for a Given Item
我的基于视图的大纲视图为其行显示自定义上下文菜单(右键单击菜单)。
菜单上的一个菜单项是"Rename...",菜单项的representedObject
属性设置为大纲视图行代表的对象:
let menu = NSMenu()
// ...other menu items...
let renameItem = NSMenuItem(
title: "Rename...",
action: #selector(OutlineViewController.rename(_:)),
keyEquivalent: "")
renameItem.representedObject = object
menu.addItem(renameItem)
在操作方面,我想以编程方式在 table 单元格 editable 中创建文本字段。问题是,我不确定如何单独从表示的对象中获取对 table 单元格 的引用。
这是我的操作方法:
@IBAction func rename(_ sender: Any) {
guard let menuItem = sender as? NSMenuItem else { return }
guard let item = menuItem.representedObject else { return }
我可以获得所表示对象 (Int) 的行:
let row = outlineView.row(forItem: item)
...和行视图 (NSTableRowView):
let rowView = outlineView.rowView(atRow: row, makeIfNecessary: false)
我可以得到列索引(Int)和列(NSTableColumn):
let columnIndex = outlineView.column(withIdentifier: "TitleColumn")
let column = outlineView.tableColumns[columnIndex]
...并尝试获取单元格视图 (NSTableCellView):
guard let cell = outlineView(outlineView, viewFor: column, item: item) as? NSTableCellView else {
return
}
最后,我尝试将文本字段设置为 editable:
guard let textField = cell.textField else {
return
}
textField.becomeFirstResponder()
所有这些测试都通过了(我设置了断点),但没有任何反应:文本字段不会变成editable(与双击时不同)。
我做错了什么?
编辑 我已经意识到当我打电话时:
outlineView(outlineView, viewFor: column, item: item)
这基本上是我的视图控制器正在实现的 NSOutlineViewDelegate
方法,因此它没有给我屏幕上已经显示的单元格,而是根据需要创建一个新副本。有点像打电话
UITableViewController.tableView(_:,cellForRowAt:)
// Data source method, creates or dequeues a new cell to pass
// back to the table for display
...而不是调用:
UITableView.cellForRowAt(_:)
// table view proper的方法; returns 现有单元格如果
// 已经在屏幕上,或遵从数据源(方法
// 以上)否则
因此,我应该查询大纲视图本身,而不是调用重新创建单元格视图的委托方法。但是,我能看到的唯一有意义的方法是:
func rowView(atRow row: Int, makeIfNecessary: Bool) -> NSTableRowView?
...其中 returns 一个 NSTableRowView...
解决了。只需要更深入地研究 API:
// Get row index
let row = outlineView.row(forItem: item)
// Get view for the whole row:
guard let rowView = outlineView.rowView(atRow: row, makeIfNecessary: false) else {
return
}
// THIS is the missing piece: Get row subview for the given column
// (= cell)
guard let cell = rowView?.view(atColumn: 0) as? NSTableCellView else {
return
}
现在我有了对屏幕上实际文本字段的引用,它变得可编辑了:
self.view.window?.makeFirstResponder(cell.textField)
我的基于视图的大纲视图为其行显示自定义上下文菜单(右键单击菜单)。
菜单上的一个菜单项是"Rename...",菜单项的representedObject
属性设置为大纲视图行代表的对象:
let menu = NSMenu()
// ...other menu items...
let renameItem = NSMenuItem(
title: "Rename...",
action: #selector(OutlineViewController.rename(_:)),
keyEquivalent: "")
renameItem.representedObject = object
menu.addItem(renameItem)
在操作方面,我想以编程方式在 table 单元格 editable 中创建文本字段。问题是,我不确定如何单独从表示的对象中获取对 table 单元格 的引用。
这是我的操作方法:
@IBAction func rename(_ sender: Any) {
guard let menuItem = sender as? NSMenuItem else { return }
guard let item = menuItem.representedObject else { return }
我可以获得所表示对象 (Int) 的行:
let row = outlineView.row(forItem: item)
...和行视图 (NSTableRowView):
let rowView = outlineView.rowView(atRow: row, makeIfNecessary: false)
我可以得到列索引(Int)和列(NSTableColumn):
let columnIndex = outlineView.column(withIdentifier: "TitleColumn")
let column = outlineView.tableColumns[columnIndex]
...并尝试获取单元格视图 (NSTableCellView):
guard let cell = outlineView(outlineView, viewFor: column, item: item) as? NSTableCellView else {
return
}
最后,我尝试将文本字段设置为 editable:
guard let textField = cell.textField else {
return
}
textField.becomeFirstResponder()
所有这些测试都通过了(我设置了断点),但没有任何反应:文本字段不会变成editable(与双击时不同)。
我做错了什么?
编辑 我已经意识到当我打电话时:
outlineView(outlineView, viewFor: column, item: item)
这基本上是我的视图控制器正在实现的 NSOutlineViewDelegate
方法,因此它没有给我屏幕上已经显示的单元格,而是根据需要创建一个新副本。有点像打电话
UITableViewController.tableView(_:,cellForRowAt:)
// Data source method, creates or dequeues a new cell to pass
// back to the table for display
...而不是调用:
UITableView.cellForRowAt(_:) // table view proper的方法; returns 现有单元格如果 // 已经在屏幕上,或遵从数据源(方法 // 以上)否则
因此,我应该查询大纲视图本身,而不是调用重新创建单元格视图的委托方法。但是,我能看到的唯一有意义的方法是:
func rowView(atRow row: Int, makeIfNecessary: Bool) -> NSTableRowView?
...其中 returns 一个 NSTableRowView...
解决了。只需要更深入地研究 API:
// Get row index
let row = outlineView.row(forItem: item)
// Get view for the whole row:
guard let rowView = outlineView.rowView(atRow: row, makeIfNecessary: false) else {
return
}
// THIS is the missing piece: Get row subview for the given column
// (= cell)
guard let cell = rowView?.view(atColumn: 0) as? NSTableCellView else {
return
}
现在我有了对屏幕上实际文本字段的引用,它变得可编辑了:
self.view.window?.makeFirstResponder(cell.textField)