1

我的基于视图的大纲视图为其行显示了一个自定义上下文菜单(右键单击菜单)。

菜单上的菜单项之一是“重命名...”,菜单项的representedObject属性设置为大纲视图行表示的对象:

    let menu = NSMenu()

    // ...other menu items...

    let renameItem = NSMenuItem(
            title: "Rename...",
            action: #selector(OutlineViewController.rename(_:)),
            keyEquivalent: "")
    renameItem.representedObject = object

    menu.addItem(renameItem)

在操作方面,我想以编程方式使表格单元格中的文本字段可编辑。问题是,我不确定如何仅从表示的对象中获取对表格单元格的引用。

这是我的操作方法:

@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
    }

最后,我尝试使文本字段可编辑:

    guard let textField = cell.textField else {
        return
    }
    textField.becomeFirstResponder()

所有这些测试都通过(我设置了断点),但没有任何反应:文本字段无法编辑(与双击时不同)。

我究竟做错了什么?


编辑我意识到当我打电话时:

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(_:) // 表格视图方法正确;如果 // 已经在屏幕上,则返回现有单元格,否则返回数据源(方法 // 上面)

因此,我应该查询大纲视图本身,而不是调用重新创建单元格视图的委托方法。但是,我能看到的唯一有意义的方法是:

func rowView(atRow row: Int, makeIfNecessary: Bool) -> NSTableRowView?

...返回一个 NSTable视图...

4

1 回答 1

3

解决了。只需要更深入地研究 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)
于 2017-09-01T10:51:18.320 回答