使用NSPopoverController创建macOS菜单栏多窗口应用:弹窗二次不显示问题
问题分析与解决
问题根源
你在关闭详情弹窗时使用了self.view.window?.close(),这种方式直接关闭了popover的宿主窗口,而非调用popover自身的关闭方法,会导致popover内部状态异常,进而影响后续新popover的正常显示。
解决方案
有两种简单的修正方式:
方式一:给DetailVC传递popover引用
- 修改表格行点击事件的代码,将新建的popover引用传递给DetailVC:
@objc func didSelectRow(){ guard let vc = NSStoryboard(name: "Main", bundle: nil).instantiateController(withIdentifier: "DetailVC") as? DetailVC else{return } let popOverView = NSPopover() popOverView.contentViewController = vc popOverView.behavior = .applicationDefined // 传递popover引用给详情控制器 vc.popover = popOverView popOverView.show(relativeTo: statusItem.button!.bounds, of: statusItem.button!, preferredEdge: .maxY) }
- 更新DetailVC的代码,添加popover属性并使用其close方法关闭弹窗:
class DetailVC: NSViewController { // 用weak避免循环引用 weak var popover: NSPopover? @IBOutlet weak var wordLbl: NSTextField! @IBOutlet weak var readingLbl: NSTextField! override func viewDidLoad() { super.viewDidLoad() } @IBAction func backBtnPressed(_ sender: Any) { popover?.close() } }
方式二:通过视图层级获取popover并关闭
无需修改表格行点击代码,直接修改DetailVC的返回按钮事件:
@IBAction func backBtnPressed(_ sender: Any) { // 通过当前视图的window获取对应的popover,调用close方法 self.view.window?.popover?.close() }
原理说明
调用NSPopover的close()方法会让系统正确处理popover的生命周期,包括资源释放、状态重置等操作,避免直接关闭窗口导致的异常,这样每次点击表格项新建的popover都能正常展示。
内容的提问来源于stack exchange,提问作者Stark
相关产品推荐
相关产品推荐

