如何仅在特定macOS版本中通过SceneBuilder添加MenuBarExtra场景?
问题原因
SwiftUI的SceneBuilder结果构建器(对应macOS 12的SwiftUI版本)不允许直接在body闭包内使用if #available这类控制流语句,因此直接写入条件分支会触发编译错误。
可行解决方案
方案一:封装条件场景为单独结构体
将仅在macOS 13+可用的MenuBarExtra场景封装成独立的Scene结构体,通过@available标记版本限制,再在主App的body中条件引入:
// 单独封装MenuBarExtra场景 @available(macOS 13.0, *) struct AppMenuBarScene: Scene { @ObservedObject var viewModel: ViewModel var body: some Scene { MenuBarExtra() { MenuBarExtraContent(model: viewModel) } label: { MenuBarExtraLabel(model: viewModel) } } } @main struct MyApp: App { @ObservedObject public var userSettings: UserSettings @ObservedObject public var viewModel: ViewModel /* 更多变量和初始化器声明 */ var body: some Scene { WindowGroup("Pipelines") { PipelineListView(model: viewModel, settings: userSettings) } .commands { AppCommands() } Settings { SettingsView(settings: userSettings) } // 条件引入封装好的场景 if #available(macOS 13.0, *) { AppMenuBarScene(viewModel: viewModel) } } }
方案二:使用可选场景属性
把版本判断逻辑移到返回可选Scene的计算属性中,SceneBuilder会自动忽略nil值,无需在body内写控制流:
@main struct MyApp: App { @ObservedObject public var userSettings: UserSettings @ObservedObject public var viewModel: ViewModel /* 更多变量和初始化器声明 */ // 计算属性返回可选的MenuBarExtra场景 private var menuBarScene: some Scene? { guard #available(macOS 13.0, *) else { return nil } return MenuBarExtra() { MenuBarExtraContent(model: viewModel) } label: { MenuBarExtraLabel(model: viewModel) } } var body: some Scene { WindowGroup("Pipelines") { PipelineListView(model: viewModel, settings: userSettings) } .commands { AppCommands() } Settings { SettingsView(settings: userSettings) } // 直接引用可选属性,旧系统下自动忽略 menuBarScene } }
方案特点
- 方案一更适合复杂场景,代码结构清晰,便于后续维护扩展;
- 方案二更简洁,适合简单的条件场景实现。
内容的提问来源于stack exchange,提问作者Erik Doernenburg
相关产品推荐
相关产品推荐

