在macOS开发中,NSPopover是一个非常有用的组件,它可以用于创建弹出窗口。然而,当用户在弹出窗口外单击时,它默认情况下并不会自动隐藏。这可能会导致用户界面上的一些问题,因为弹出窗口会一直显示在屏幕上,直到用户手动关闭它。为了解决这个问题,我们可以通过监听焦点丢失事件,并在事件发生时隐藏NSPopover。
要实现这个功能,我们首先需要创建一个NSPopover的实例,并将其设置为我们想要显示的视图控制器的contentViewController属性。然后,我们可以通过实现NSPopoverDelegate协议中的popoverDidShow方法来监听弹出窗口的显示事件。在这个方法中,我们可以为主视图添加一个全局事件监视器,以便在用户单击弹出窗口外部时接收到焦点丢失事件。下面是一个示例代码,演示了如何使用NSPopover和NSPopoverDelegate来实现焦点丢失时隐藏弹出窗口的功能:swiftimport Cocoaclass ViewController: NSViewController, NSPopoverDelegate { var popover: NSPopover! override func viewDidLoad() { super.viewDidLoad() popover = NSPopover() popover.contentViewController = SomeViewController() popover.delegate = self } func popoverDidShow(_ notification: Notification) { if let window = view.window { NSEvent.addGlobalMonitorForEvents(matching: .leftMouseDown) { [weak self] event in if let strongSelf = self { if !window.frame.contains(event.locationInWindow) { strongSelf.popover.performClose(nil) } } } } }}class SomeViewController: NSViewController { override func loadView() { view = NSView(frame: NSRect(x: 0, y: 0, width: 200, height: 100)) view.wantsLayer = true view.layer?.backgroundColor = NSColor.red.cgColor }}在上面的代码中,我们首先创建了一个NSPopover的实例,并将其contentViewController属性设置为SomeViewController的实例。然后,我们将视图控制器的delegate属性设置为自身,以便能够监听popoverDidShow事件。在popoverDidShow方法中,我们使用NSEvent的addGlobalMonitorForEvents方法添加了一个全局事件监视器。这个监视器会监听所有的鼠标左键单击事件,并在用户单击弹出窗口外部时触发。在事件处理程序中,我们首先检查事件发生的位置是否在主视图窗口的范围内。如果不在范围内,我们就调用popover的performClose方法来隐藏弹出窗口。代码示例上面的代码中,我们创建了一个NSViewController的子类SomeViewController,并在其loadView方法中创建了一个红色的NSView。这个视图将作为弹出窗口的内容显示。你可以根据自己的需要自定义视图的外观和布局。使用NSPopoverDelegate监听焦点丢失事件在上面的代码中,我们通过实现NSPopoverDelegate协议中的popoverDidShow方法来监听弹出窗口的显示事件。在这个方法中,我们添加了一个全局事件监视器,以便在用户单击弹出窗口外部时接收到焦点丢失事件。隐藏弹出窗口在焦点丢失事件处理程序中,我们使用popover的performClose方法来隐藏弹出窗口。这将导致弹出窗口消失,并且不再显示在屏幕上。通过以上代码,我们成功实现了在焦点丢失时隐藏弹出窗口的功能。这样,当用户单击弹出窗口外部时,弹出窗口会自动隐藏,提升了用户界面的友好性和易用性。