我的基于视图的大纲视图为其行显示自定义上下文菜单(右键单击菜单)。
菜单上的一个菜单项是“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 行查看...
答案 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