macOS开发中NSColorPanel点击空白消失后无法再次唤起
macOS NSColorPanel 点击空白消失后无法重新唤起问题修复
问题场景
开发中配置了statusBarItem用于触发显示NSColorPanel,对应效果如下:
按钮点击时原调用代码如下:
@IBAction func showColour( button:NSButton ){ DispatchQueue.main.async { NSApplication.shared.orderFrontColorPanel(self) print( "panel frame:\(NSColorPanel.shared.frame), is visible:\(NSColorPanel.shared.isVisible )" ) } }
实际测试存在异常:
- 点击面板自带关闭按钮关闭颜色面板后,再次点击按钮可正常唤起面板
- 点击空白区域导致
NSColorPanel消失后,后续点击按钮无法重新唤起面板,此时日志输出显示面板frame参数有效,且isVisible属性为true
问题根源
NSColorPanel是系统提供的NSPanel子类,默认开启了hidesOnDeactivate属性:当面板失焦(比如点击其他空白区域)时,系统会自动将面板移出窗口层级实现隐藏效果,但不会同步更新isVisible属性的标记。此时调用orderFrontColorPanel方法时,系统判定面板已经处于可见状态,不会执行重新唤起、窗口置前的逻辑,就会出现点击按钮无响应的问题。
可行修复方案
替换原按钮点击逻辑为如下代码即可:
@IBAction func showColour( button:NSButton ){ DispatchQueue.main.async { let colorPanel = NSColorPanel.shared // 面板未处于焦点状态时先重置窗口状态,解决状态不同步问题 if !colorPanel.isKeyWindow { colorPanel.orderOut(nil) } // 配置面板属性:关闭失焦自动隐藏、设为浮动面板层级 colorPanel.hidesOnDeactivate = false colorPanel.isFloatingPanel = true // 针对状态栏无Dock图标的应用,需要先激活当前应用 NSApp.activate(ignoringOtherApps: true) // 重新将面板置为关键窗口并移到最前 NSApp.orderFrontColorPanel(self) colorPanel.makeKeyAndOrderFront(nil) } }
补充优化建议
如果不需要面板失焦自动隐藏的特性,可以在应用启动完成的回调中提前配置全局面板属性,避免重复设置:
func applicationDidFinishLaunching(_ aNotification: Notification) { NSColorPanel.shared.hidesOnDeactivate = false NSColorPanel.shared.isFloatingPanel = true }
内容的提问来源于stack exchange,提问作者reza23
相关产品推荐
相关产品推荐

