#swift #swiftui #contextmenu #swiftui-contextmenu
Вопрос:
Я пытаюсь настроить SwiftUI .contextMenu
с помощью кнопки, которая переключает Bool
значение. Текст кнопки контекстного меню должен изменяться при Bool
переключении. Но контекстное меню не обновляется. Есть ли способ принудительно обновить контекстное меню?
Пример кода, описывающего проблему:
import SwiftUI
struct Item: Identifiable {
let id = UUID()
let user: String
var active: Bool
}
struct ContentView: View {
@State var items: [Item] = [
Item(user: "Daniel",active: false),
Item(user: "Jack", active: true),
Item(user: "John", active: true)
]
@State var isOn : Bool = false
var body: some View {
List {
ForEach(items) { item in
VStack {
Text("(item.user)")
HStack {
Text("Active ? ")
Text(item.active ? "YES": "NO")
}
}.contextMenu{
Button(action: {
let index = items.firstIndex{$0.user == item.user}
items[index!].active.toggle()
}) {
Text(item.active ? "Set as Active": "Set as Inactive")
}
}
}
}
}
}
Ответ №1:
Это ошибка в SwiftUI, и она все еще исправлена в симуляторе бета-версии 2 Xcode 13.2.
Мне удалось обойти это, дублируя элемент списка в обеих ветвях if item.active
инструкции, например:
struct ContentView: View {
@State var items: [Item] = [
Item(user: "Daniel",active: false),
Item(user: "Jack", active: true),
Item(user: "John", active: true)
]
var body: some View {
List {
ForEach(items) { item in
// work around SwiftUI bug where
// context menu doesn't update
if item.active { listItem(for: item) }
else { listItem(for: item) }
}
}
}
private func listItem(for item: Item) -> some View {
VStack {
Text("(item.user)")
HStack {
Text("Active ? ")
Text(item.active ? "YES": "NO")
}
}
.contextMenu {
Button(item.active ? "Deactivate" : "Activate") {
if let index = items.firstIndex(where: { $0.id == item.id }) {
items[index].active.toggle()
}
}
}
.id(item.id)
}
}