Swift 5 - Mac OS - NSTrackingArea 重叠视图

Swift 5 - Mac OS - NSTrackingArea overlapping views

目前我在按钮(NSButton)方面遇到了一些小问题,这些按钮上面有一个跟踪区域和视图(NSView overlay),这是我的设置:

自定义按钮:

class AppButton: NSButton {
    override func updateTrackingAreas() {
        super.updateTrackingAreas()
        let area = NSTrackingArea(
            rect: self.bounds,
            options: [.mouseEnteredAndExited, .activeAlways],
            owner: self,
            userInfo: nil
        )
        self.addTrackingArea(area)
    }
    override func mouseEntered(with event: NSEvent) {
        NSCursor.pointingHand.set()
    }
    override func mouseExited(with event: NSEvent) {
        NSCursor.arrow.set()
    }
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

此按钮的实例 class 用于非常基本的 NSView

当我将鼠标悬停在按钮上时,光标会正确更改。

当我单击按钮时,会在按钮上方打开一个新的叠加层 (NSView)...

问题由此开始:

当我将鼠标悬停在放置我的按钮的叠加层上时,光标仍然发生变化...

我不知道 NSTrackingArea 正在浏览所有视图..

我该如何解决这个问题?

我可以在叠加层 (NSView) 上设置任何 属性 以某种方式禁用按钮上的 NSTrackingArea 吗?

谢谢!!

您可以子类化 NSView 并为事件添加本地监控。检查事件是否在视图上发生,如果为真 return nil。这将避免传播被监视的事件。如果事件在视图框架之外,您可以正常传播它return监控事件。

class CustomView: NSView {
    override func viewWillMove(toSuperview newSuperview: NSView?) {
        super.viewWillMove(toSuperview: newSuperview)
        wantsLayer = true
        layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor
        layer?.borderWidth = 1
        NSEvent.addLocalMonitorForEvents(matching: [.mouseEntered, .mouseExited, .leftMouseDown]) { event in
            if self.frame.contains(event.locationInWindow) {
                // if cursor is over the view just return nil to do not propagate the events
                return nil
            }
            return event
        }
    }
}

如果您试图停止来自 viewController 的鼠标事件,请在 viewDidLoad

中添加此代码
NSEvent.addLocalMonitorForEvents(matching: [.mouseEntered, .mouseExited, .leftMouseDown]) { event in
        if self.view.frame.contains(event.locationInWindow) {
            return nil
        }
        return event
    }