swift 如何仅在某些版本的macOS上将场景包含在SceneBuilder中?

mbzjlibv  于 2023-01-29  发布在  Swift
关注(0)|答案(1)|浏览(193)

我的问题如下:我有一个应用程序使用MenuBarExtra()场景类型,这是在macOS 13中引入的。但我也想有一个macOS 12版本的应用程序,只是没有那个场景。
我已经研究了使用@availableif #available的各种排列,但还没有能够找到编译的东西。
原则上,这是我所希望的:

@main
struct MyApp: App {
    @ObservedObject public var userSettings: UserSettings
    @ObservedObject public var viewModel: ViewModel
    /* more variables and initializer declarations */  

   var body: some Scene {
        WindowGroup("Pipelines") {
            PipelineListView(model: viewModel, settings: userSettings)
        }
        .commands {
            AppCommands()
        }
        Settings {
            SettingsView(settings: userSettings)
        }
        if #available(macOS 13.0, *) {
            MenuBarExtra() {
                MenuBarExtraContent(model: viewModel)
            } label: {
                MenuBarExtraLabel(model: viewModel)
            }
        }
    }
}

但是这段代码不能编译,编译器抱怨"包含控制流语句的闭包不能与结果生成器'SceneBuilder'一起使用"。
你觉得我可以试试吗?

1tu0hz3e

1tu0hz3e1#

SceneBuilder不允许使用条件语句,并且没有AnyScene类型橡皮擦,因此您不能使用一个MyApp类型返回不同的Scene定义,具体取决于macOS版本。
相反,创建两个符合App的类型:一个用于macOS 13和更高版本,一个用于更旧的系统。不要将@main注解附加到这两种类型中的任何一种。将常见的内容分解到符合Scene的第三种类型中。
下面是常见的Scene

struct CommonScene: Scene {
    @ObservedObject var userSettings: UserSettings
    @ObservedObject var viewModel: ViewModel

   var body: some Scene {
        WindowGroup("Pipelines") {
            PipelineListView(model: viewModel, settings: userSettings)
        }
        .commands {
            AppCommands()
        }
        Settings {
            SettingsView(settings: userSettings)
        }
    }
}

用于旧系统的App只是封装了CommonScene

struct OldSystemApp: App {
    @StateObject var userSettings = UserSettings()
    @StateObject var viewModel = ViewModel()

    var body: some Scene {
        CommonScene(
            userSettings: userSettings,
            viewModel: viewModel
        )
    }
}

适用于macOS 13的App增加了MenuBarExtra

struct App13: App {
    @StateObject var userSettings = UserSettings()
    @StateObject var viewModel = ViewModel()
    
    var body: some Scene {
        CommonScene(
            userSettings: userSettings,
            viewModel: viewModel
        )
        
        MenuBarExtra() {
            MenuBarExtraContent(model: viewModel)
        } label: {
            MenuBarExtraLabel(model: viewModel)
        }
    }
}

最后,根据macOS 13是否可用,使用static func main()编写您自己的小类型,并将@main添加到该类型中,其中static func main()运行相应App类型的main

@main
struct MyMain {
    static func main() {
        if #available(macOS 13.0, *) {
            App13.main()
        } else {
            OldSystemApp.main()
        }
    }
}

相关问题