如何在macOS Catalyst应用中为NSToolbar设置深色模式?
问题根源
Mac Catalyst 架构中,NSToolbar 属于 AppKit 层管控的组件,默认不响应 UIKit 层的窗口 overrideUserInterfaceStyle 属性配置,所以会出现窗口内容和工具栏外观不一致的情况。
解决方案
方案一:全局同步应用外观(推荐)
如果你的应用外观是全局统一配置的,直接修改 AppKit 层全局应用外观即可一次性同步工具栏、系统菜单、弹窗等所有原生组件的样式,实现成本最低,一致性最好。
代码示例:
#if targetEnvironment(macCatalyst) import AppKit #endif func setGlobalAppearance(_ style: UIUserInterfaceStyle) { // 原有UIKit层窗口配置 UIApplication.shared.windows.forEach { $0.overrideUserInterfaceStyle = style } // 适配Mac Catalyst同步工具栏 #if targetEnvironment(macCatalyst) let nsAppearance: NSAppearance? switch style { case .light: nsAppearance = NSAppearance(named: .aqua) case .dark: nsAppearance = NSAppearance(named: .darkAqua) case .unspecified: nsAppearance = nil // 跟随系统 @unknown default: nsAppearance = nil } NSApp.appearance = nsAppearance #endif }
方案二:单窗口独立控制工具栏外观
如果你的应用需要支持不同窗口使用不同外观,可以通过KVC获取UIWindow对应的底层NSWindow实例,单独配置工具栏的外观:
#if targetEnvironment(macCatalyst) import AppKit extension UIWindow { // 获取对应AppKit层的NSWindow实例,该接口在Mac Catalyst环境下可安全过审 var associatedNSWindow: NSWindow? { value(forKey: "nsWindow") as? NSWindow } } #endif func setWindowAppearance(window: UIWindow, style: UIUserInterfaceStyle) { window.overrideUserInterfaceStyle = style #if targetEnvironment(macCatalyst) guard let nsWindow = window.associatedNSWindow, let toolbar = nsWindow.toolbar else { return } switch style { case .light: toolbar.appearance = NSAppearance(named: .aqua) case .dark: toolbar.appearance = NSAppearance(named: .darkAqua) case .unspecified: toolbar.appearance = nil @unknown default: toolbar.appearance = nil } #endif }
注意事项
- 两种方案均只需要在切换外观的逻辑处调用一次即可,无需额外监听系统外观变更
- 方案二使用的KVC取值方式已经被大量主流应用使用,不会触发App Store审核拒绝
内容的提问来源于stack exchange,提问作者iosdeveloper
相关产品推荐
相关产品推荐

