NSWindow.contentView.hittest() 没有到达 NSOutlineView 的子视图

NSWindow.contentView.hittest() Doesn't Reach Subviews of NSOutlineView

我的应用 window 有一个包含三个窗格的拆分视图;最左边的窗格承载基于视图的大纲视图。

当我单击该大纲视图上的某处时,我想确定被单击的层次结构中最底部的子视图。也就是说,点击了哪一行,哪个单元格,最终点击了单元格的哪个子视图(控件)。

我尝试在托管视图控制器上重写 mouseDown(with:),但它没有被调用;我怀疑大纲视图以某种方式占用了事件,所以我决定直接在我的 NSOutlineView subclass 本身上覆盖该方法。这行得通。但是,从那里我不能比大纲视图本身更进一步:

class MyOutlineView: NSOutlineView {

override func mouseDown(with event: NSEvent) {
    if let view = self.window?.contentView?.hitTest(event.locationInWindow) {
        Swift.print("\(view.className)")
    }
}

...打印:

MyModule. MyOutlineView

hittest() 的文档如下:

Returns the farthest descendant of the view in the view hierarchy (including itself) that contains a specified point, or nil if that point lies completely outside the view. This method is used primarily by an NSWindow object to determine which view should receive a mouse-down event. You’d rarely need to invoke this method, but you might want to override it to have a view object hide mouse-down events from its subviews. This method ignores hidden views.

如何对大纲视图的最顶层子视图进行命中测试?

mouseDown(with:) 在视图上调用,而不是在控制器上调用。 通常大纲视图中的控件处理 mouseDown。

但是如果你想找到控件,是的,-[NSTableView(NSTableViewRowHeaderSupport) hitTest:] 把事情搞砸了。解决方法:获取行和列,获取单元格视图并在单元格视图上调用 hitTest

override func mouseDown(with event: NSEvent) {
    let localPoint = self.convert(event.locationInWindow, from: nil)
    let column = self.column(at: localPoint)
    let row = self.row(at: localPoint)
    if column >= 0 && row >= 0 {
        if let cellView = self.view(atColumn: column, row: row, makeIfNecessary: false) {
            if let cellSuperViewPoint = cellView.superview?.convert(localPoint, from: self) {
                if let view = cellView.hitTest(cellSuperViewPoint) {
                    Swift.print("\(view.className)")
                }
            }
        }
    }
}