You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NSPopoverController创建macOS菜单栏多窗口应用:弹窗二次不显示问题

问题分析与解决

问题根源

你在关闭详情弹窗时使用了self.view.window?.close(),这种方式直接关闭了popover的宿主窗口,而非调用popover自身的关闭方法,会导致popover内部状态异常,进而影响后续新popover的正常显示。

解决方案

有两种简单的修正方式:

方式一:给DetailVC传递popover引用

  1. 修改表格行点击事件的代码,将新建的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)
}
  1. 更新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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 22:07:54