Я добавляю меню сортировки в свое приложение SwiftUI для macOS. Рядом с некоторыми элементами могут быть отмечены галочки. Для каждого пункта меню я создаю элемент Toggle, привязанный к @State Bool. Когда элемент щелкнут, я хотел бы запустить дополнительный код для обновления сортировки, поэтому я добавил .onChange, но он никогда не вызывается. Флажок для элемента появляется и исчезает, как я и ожидал, но .onChange никогда не попадает.
Вот пример создания пункта меню macOS с галочкой. «Изменение» никогда не печатается, и установленная там точка останова никогда не срабатывает.
import SwiftUI
struct ViewMenuCommands: Commands {
@State
var isAlphabetical = false
@CommandsBuilder var body: some Commands {
CommandMenu("ViewTest") {
Toggle("Alphabetical", isOn: $isAlphabetical)
.onChange(of: isAlphabetical) { value in
print( "change" )
}
}
}
}
И вот где я добавляю меню в приложение:
import SwiftUI
@main
struct MenuToggleTestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.commands {
ViewMenuCommands()
}
}
}
Проблема возникает из-за того, что @State
не уведомляет Commands
об изменении — @State
уведомляет только View
об изменении.
Решение состоит в том, чтобы обернуть ваш пункт меню в вид, который может реагировать на изменения (через @State
или ObservableObject
— я выбрал последнее).
Пример:
@main
struct MainApp: App {
@StateObject var menuState = MenuState()
var body: some Scene {
WindowGroup {
ContentView()
}
.commands {
CommandMenu("ViewTest") {
AlphabeticalMenuItem(menuState: menuState)
}
}
}
}
class MenuState : ObservableObject {
@Published var isAlphabetical = false
}
struct AlphabeticalMenuItem : View {
@ObservedObject var menuState : MenuState
var body: some View {
Toggle("Alphabetical", isOn: $menuState.isAlphabetical)
.onChange(of: menuState.isAlphabetical) { value in
print( "change" )
}
}
}
Ясно, что @State должен находиться внутри View, и я объявил его с помощью Commands. Спасибо.