在NSTableView中获取自定义NSTableCellView的位置

时间:2017-01-26 19:16:02

标签: swift macos cocoa nstableview

我正在尝试将NSPopover添加到NSTableView中的自定义NSTableCellView。我能够使NSPopover显示对应于正确的元素,但是弹出窗口的位置不正确。为了清楚我的问题以防有人对设计提出更好的建议:当用户将鼠标悬停在联系人表格中的联系人时,我想在弹出框中显示该联系人的更多信息(无需点击)

目前NSPopover初始化如下: contactPopover = NSPopover(contentViewController: contactViewController, sender: allContactsViewController.view, bounds: contactTableCellView.frame) 初始化程序只是轻轻设置popover行为并调用popover.show(...) 其中contactTableCellView是我想要的联系人的表格单元格视图。

问题是contactTableCellView.frame总是有(x,y)=(0,0),因为这是自定义NSTableCellView的模板在xib中开始的地方。为了正确地将弹出窗口放在桌子上,我需要获取表格单元格视图相对于NSTable原点的位置。

现在每个NSTableCellView都有鼠标跟踪设置,所以在鼠标输入时,我通知联系人列表显示弹出窗口,我在其中传递相应的鼠标输入表格单元格视图。这使我在尝试获取相对于表的位置时可以访问表格单元格视图,但是我在文档中找不到有关如何获取表格单元格视图相对于表格原点的实际位置的任何内容。 / p>

注意:https://developer.apple.com/reference/appkit/nstableview https://developer.apple.com/reference/appkit/nstablecellview

2 个答案:

答案 0 :(得分:1)

我不确定这是什么:

contactPopover = NSPopover(contentViewController: contactViewController, sender: allContactsViewController.view, bounds: contactTableCellView.frame)

该方法来自哪里?它不属于NSPopover本身。

无论如何,这应该做你想要的,假设一个没有多余行李的弹出窗口:

contactPopover.show(relativeTo:contactTableCellView.bounds of:contactTableCellView preferredEdge:.minY)

这将使popover相对于单元格视图的位置,而无需弄清楚单元格视图在表视图中的位置。

答案 1 :(得分:0)

使用@KenThomases离开convo,最好的方法是让表格视图单元格自己管理弹出窗口,但这只是一半可能。我会解释一下:

由于表重绘了表格单元格视图,因此contactTableCellView无法保证它在NSPopover的整个生命周期内都存在。为了使popover与contactTableCellView无关的生命周期存在,我的类中存在一个NSPopover对象,其中包含NSTableView(让我们称之为addressBookViewController)。所以addressBookViewController将有一个名为contactPopover的成员,只要addressBookViewController仍在内存中,我们就可以确定popover会存在。这个问题是获得popover链接的正确边界。

如果你将当前的contactTableCellView传递回addressBookViewController并使用类似contactPopover.show(relativeTo:contactTableCellView.bounds of:contactTableCellView preferredEdge:.minY)之类的东西作为@KenThomases,你会看到弹出窗口被卡在NSTableView中的第一个/ top元素中,无论是什么元素我将鼠标悬停在上面,但我希望弹出框指向悬停在上面的元素。

我找不到任何参考资料来证明我的假设,但从我的结果来看,似乎NSTableView的单元格/视图包含我创建的自定义ContactTableCellView。这就是我得到“contactTableCellView.frame总是有(x,y)=(0,0)”的原因。框架始终相对于父对象,在这种情况下,父对象是与TableCellView具有相同大小的视图/单元格。而这个外部视图有我想要/期望contactTableCellView.frame的框架。说清楚这一点:

contactTableCellView.superView?.frame在NSTableView中给出了正确的(x,y),并且由于各种原因,由于contactTableCellView被重绘,因此不会删除此帧。使用我的发现,我能够得到一个相对于正确元素的弹出框,就像我在Swift 3中大致想要的那样:

class AddressBookViewController {
...
var contactCardPopover: NSPopover?
...

func showContact(sender: AnyObject, contact: ContactVM) {
    guard let contactTableCellView = sender as? ContactTableCellView else { return }

    // when contactCardVC is non-nil, a popover currently open. This makes sure 2 don't open in the same tableView.
    if contactViewController == nil {
        contactCardViewController = ContactViewController(contact: contact)

        // this here is the important part!!!! Using the contactTableCellView.superview
        if let tableCell = participantTableCellView.superview {

            contactCardPopover = NSPopover(contentViewController: contactCardViewController, sender: tableCell, bounds: tableCell.frame)
            contactCardPopover.delegate = self
        }
    }
}

}

所以ContactTableCellView的超级视图有正确的框架,所以我的NSPopover可以像我原来想要的那样在自定义NSTableCellView上工作!只花了几个小时来弄清楚这一特定部分。