Just did that for my own app, which had a pre-existing setup that made it easy.
Essentially, it's this
@main
struct MyApp: App {
@StateObject private var appStateRegistry = AppStateRegistry.shared
var body: some Scene {
WindowGroup {
MainView()
.environmentObject(appStateRegistry)
.environmentObject(appStateRegistry.tabStateHandler)
}
}
}
// See https://www.fivestars.blog/articles/app-state/ for why we need both AppStateRegistry and TabStateHandler
class AppStateRegistry: ObservableObject {
static let shared = AppStateRegistry()
var tabStateHandler = TabStateHandler()
}
public enum MainTab: String {
case tab1, tab2, tab3
}
class TabStateHandler: ObservableObject {
@Published var selection: MainTab = .tab1
}
struct MainView: View {
@EnvironmentObject var tabStateHandler: TabStateHandler
var body: some View {
TabView(selection: $tabStateHandler.selection) {…}
}
}
And now in your AppIntent all you need to do is
// It's not the same enum since you could have more (or less) options here
public enum ShortcutableView: String, AppEnum {
case tab1, tab2
}
struct OpenViewIntent: AppIntent {
static var openAppWhenRun: Bool = true // Make sure you have this
@Parameter(title: "View")
var view: ShortcutableView
@MainActor
func perform() async throws -> some IntentResult {
switch view {
case .tab1:
AppStateRegistry.shared.tabStateHandler.selection = .tab1
case .tab2:
AppStateRegistry.shared.tabStateHandler.selection = .tab2
}
return .result()
}
}