В этом простом примере приложения у меня есть следующие требования:
- иметь несколько окон, каждое из которых имеет собственное
ViewModel
- переключение
Toggle
в одном окне не должно не обновлять другое окно - Я также хочу иметь возможность переключаться через меню
В настоящий момент первые два пункта не даны, но последний пункт работает. Я уже знаю, что, когда я перемещаю единственный источник истины ViewModel
в ContentView
, работает для первых двух точек, но тогда у меня не будет доступа на уровне WindowGroup
, где я вводю команды.
import SwiftUI
@main
struct ViewModelAndCommandsApp: App {
var body: some Scene {
ContentScene()
}
}
class ViewModel: ObservableObject {
@Published var toggleState = true
}
struct ContentScene: Scene {
@StateObject private var vm = ViewModel()// injecting here fulfills the last point only…
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(vm)
.frame(width: 200, height: 200)
}
.commands {
ContentCommands(vm: vm)
}
}
}
struct ContentCommands: Commands {
@ObservedObject var vm: ViewModel
var body: some Commands {
CommandGroup(before: .toolbar) {
Button("Toggle Some State") {
vm.toggleState.toggle()
}
}
}
}
struct ContentView: View {
@EnvironmentObject var vm: ViewModel//injecting here will result in window independant ViewModels, but make them unavailable in `ContactScene` and `ContentCommands`…
var body: some View {
Toggle(isOn: $vm.toggleState, label: {
Text("Some State")
})
}
}
Как я могу выполнить эти требования - есть ли решение SwiftUI для этого или мне придется реализовать SceneDelegate
(это решение в любом случае?)?
Редактировать:
Чтобы быть более конкретным: я хотел бы знать, как я могу создать экземпляр ViewModel для каждой отдельной сцены и также узнать из строки меню, какую ViewModel нужно изменить.
ViewModel
с новымUUID
для этого конкретного нового окна / сцены. Я просто не могу понять, где нужно создать этотUUID
. Придется еще немного поиграть, чтобы, возможно, найти способ ... Но это намного ближе, чем когда-либо прежде, и я ценю ваши усилия. 31.01.2021menuBuilder
запускается в самом начале. Чтобы иметь возможность воздействовать на тумблер, он должен быть там с самого начала. Я не особо в это разбирался. НоDocumentGroup
создает документы наinit
, что позволяет им иметь строку меню для определенных документов. Кажется, это то, что вы пытаетесь сделать, аналогично тому, что вы пытаетесь сделать. 31.01.2021ViewModel
на уровнеButton
, я думаю. Возможно, следующим шагом станет изучениеDocumentGroup
... 01.02.2021