NSOutlineView - 为给定项目获取NSTableCellView

时间:2017-09-01 10:32:39

标签: macos nsoutlineview nstablecellview

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

菜单上的一个菜单项是“Rename ...”,菜单项的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(_ :)    //适当的表视图方法;返回现有单元格if    //已经在屏幕上,或者推迟到数据源(方法    //上面)否则

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

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

...返回NSTable 查看...

1 个答案:

答案 0 :(得分:1)

解决了它。只需要深入了解API:

self.view.window?.makeFirstResponder(cell.textField)

现在我已经在屏幕上显示了实际的文本字段,它变得可以编辑:

data Point = Point { ptX :: Double, ptY :: Double }
data Cluster = Cluster { clusterPts :: [Point] }

minMaxPoints :: [Point] -> (Point, Point)
minMaxPoints ps =
   (Point minX minY
   ,Point maxX maxY)
     where minX = minimum $ map ptX ps
           maxX = maximum $ map ptX ps
           minY = minimum $ map ptY ps
           maxY = maximum $ map ptY ps

main = do

    let pointDistance :: Point -> Point -> Double
        pointDistance (Point x1 y1) (Point x2 y2) = sqrt $ (x1-x2)^2 + (y1-y2)^2

        cluster1 :: [Point] -> [Cluster]
        cluster1 ps =
          let (mn, mx) = minMaxPoints ps
              (psmn, psmx) = partition (\p -> pointDistance mn p < pointDistance mx p) ps
          in [ Cluster psmn, Cluster psmx ]

        cluster :: [Point] -> [Cluster]
        cluster ps =
          cluster1 ps >>= \cl@(Cluster c) ->
          if length c > 5
          then cluster c
          else [cl]

        testPts :: [Point]
        testPts = map (uncurry Point)
          [ (1,0), (2,1), (0,2)
          , (5,2), (4,3), (4,4)
          , (8,2), (9,3), (10,2)
          , (11,4), (12,3), (13,3) ]

        main = mapM (map (\p -> (ptX p, ptY p)) . clusterPts) $ cluster testPts

    print main