Mac Catalyst 适配坑位:唤起 macOS 分享时的菜单栏色差问题
2023-11-15 03:57:13
**引言**
Mac Catalyst 是一种由苹果公司推出的,用于将适用于 iPhone、iPad 的 App 移植到 Mac 平台的工具集。使用 Mac Catalyst 可以大幅减少移植 App 的工作量,但随之而来也带来了一定兼容适配方面的挑战。
本文将重点探讨 Mac Catalyst 适配过程中,App 唤起 macOS 分享菜单栏时,菜单栏颜色差异所产生的视觉问题。针对此问题,本文将进行详细的成因浅析,并进而提供行之有效的适配建议。
**问题成因浅析**
当在 Mac Catalyst 中使用 SwiftUI 开发 App,并唤起 macOS 分享菜单栏时,会出现与原生 Mac App 明显的菜单栏颜色差异。其具体表现形式为,菜单栏的颜色明显深于原生 Mac App 的菜单栏,如下所示:

深究其成因,主导 Mac Catalyst 分享菜单栏视觉表现的是 AppKit 的 NSSharingService.
在 AppKit 中,可以通过如下 API 控制菜单栏按钮颜色:
public var highlightedMenuItemBackgroundColor: NSUIC.BackgroundColor
而 SwiftUI 并为开发者提供该 API 的直接访问权限。
经过一番探索,我们找到了两种曲线救国的方式:
1. 继承 AppKit 中的 NSSharingService 并封装成 SwiftUI 组件。
2. 利用 SwiftUI 中的 ViewModifier 替换 NSSharingService 的菜单栏按钮颜色。
**适配建议**
**方案一:继承 NSSharingService 并封装 SwiftUI 组件**
**适用场景:** SwiftUI 开发且兼容性优先的 App。
1. 创建一个继承 NSSharingService 的 SwiftUI 组件,如 SharingService
2. 实现 highlightedMenuItemBackgroundColor setter
3. 将 SharingService 替换 AppKit 中的 NSSharingService
class SharingService: NSSharingService {
@Environment(.color.primary) var primaryColor
override var highlightedMenuItemBackgroundColor: NSUIC.BackgroundColor {
get {
super.highlightedMenuItemBackgroundColor
}
set {
guard let color = primaryColor else {
return
}
super.highlightedMenuItemBackgroundColor = .init(color)
}
}
}
struct ContentView: View {
var body: some View {
Button("Share") {
let mySharingService = SharingService()
mySharingService.perform(withItems: [""])
}
}
}
**方案二:ViewModifier**
**适用场景:** SwiftUI 开发且适配灵活度优先的 App。
1. 创建一个 ViewModifier,如 MenuBarColorPreferenceKey
2. 实现 body(content:)
3. 将 MenuBarColorPreferenceKey 应用于 SharingService
struct MenuBarColorPreferenceKey: ViewModifier {
var color: Color
init(color: Color) {
self.color = color
}
func body(content: Content) -> some View {
content
.frame(width: 100, height: 100)
.background(color)
.onPreferenceChange(NSSharingService.PreferenceKey) { color in
NSApp.menu?._menuBarView._color = .init(color)
}
}
}
struct ContentView: View {
@Environment(.color.primary) var primaryColor
var body: some View {
Button("Share") {
let mySharingService = NSSharingService()
mySharingService.perform(withItems: [""])
}
.background(
menuBarColorPreferenceKey(color: primaryColor)
)
}
}
**总结与展望**
在 Mac Catalyst 适配过程中,唤起 macOS 分享菜单栏时产生的菜单栏颜色差异是开发中一个很容易被忽视的问题。本文从成因入手,提出了两种各具优势的适配建议,供各位开发者参考。
需要注意的是,在适配过程中,需要权衡兼容性和灵活性。如果兼容性优先,可以采用方案一;如果灵活性优先,方案二则更加适用。
随着 Mac Catalyst 技术的不断演进,我们相信开发者在进行跨