#ios #arrays #swift #button #swiftui
#iOS #массивы #swift #кнопка #swiftui
Вопрос:
В настоящее время у меня есть цикл foreach, который вводит список элементов, каждый с кнопкой, которая выполняет определенную функцию. Как отключить отдельную кнопку при нажатии только для одного пользователя без использования учетных записей пользователей? Заранее большое спасибо!
Дополнительный контекст: у каждого элемента есть то, что по сути является кнопкой «Добавить», которая добавляет 1 к полю в БД, каждому пользователю должно быть разрешено нажимать кнопку только один раз, поэтому мне нужно отключить ее после одного щелчка. На данный момент они могут нажимать на нее столько раз, сколько захотят, число в базе данных будет продолжать расти.
Код
ForEach(items.indices, id: .self) { i in
HStack {
Text(items[i].name)
Spacer()
Button(action: {
self.performFunction()
}) {
Text("Yes")
.font(.system(size: 14))
.foregroundColor(Color.white)
.padding(.horizontal)
}
}
}
Ответ №1:
Предполагая, что «Элемент» является структурой или классом, вы всегда можете просто добавить логический флаг, чтобы указать, был ли выбран этот элемент.
Так, например, что-то вроде этого:
struct Item {
var name: String
var selected: Bool = false
}
struct ContentView: View {
@State private var items: [Item] = [
Item(name: "Bob"),
Item(name: "Joe"),
Item(name: "John Cena")
]
var body: some View {
ForEach(items.indices, id: .self) { i in
HStack {
Text(items[i].name)
Spacer()
Button(action: {
items[i].selected.toggle()
}) {
Text(items[i].selected ? "Yes" : "No")
.font(.system(size: 14))
.foregroundColor(.black)
.padding(.horizontal)
}
}
}
}
}
Комментарии:
1. Это работает только с кодом, но есть функция, которую я также вызываю на этой кнопке, которая, похоже, сбрасывает ее на false, и я не уверен, почему
func yesTrigger() { let db = Firestore.firestore() db.collection("mainItems").document(itemID).collection("items").document("(self.selection)").updateData([AnyHashable("yes"): FieldValue.increment(Int64(1))]) }
Ответ №2:
Неясен контекст … но возможное решение — создать массив той же длины, items
что и и использовать его для хранения нажатого состояния, например
@State private var clicked: [Bool] // initiate with array of false when `items` ready
...
Button(action: {
self.performFunction()
self.clicked[i] = true // << here !!
}) {
Text("Yes")
.font(.system(size: 14))
.foregroundColor(Color.white)
.padding(.horizontal)
}
.disabled(self.clicked[I]) // // << here !!
Комментарии:
1. Это имеет смысл, но когда я ввожу этот код, в разделе предварительного просмотра я получаю
'View' initializer is inaccessible due to 'private' protection level
,Missing argument for parameter 'clicked' in call
иInsert ', clicked:<#[Bool]#>'
2. Также добавлен дополнительный контекст к вопросу