Почему значение @State не обновляется

#swift #swiftui

#swift #swiftui

Вопрос:

У меня есть три кнопки, каждая кнопка соответствует значению в массиве данных. Когда пользователь нажимает кнопку, соответствующее значение отображается в окне листа. Вот мой код:

 struct TestView: View {
    @State var data: [Int] = [100, 200, 300]
    @State var presented: Bool = false
    @State var index4edit: Int = 1
    
    var body: some View {
        HStack{
            ForEach(1..<4){ index in
                Button(action: {
                    index4edit = index
                    presented.toggle()
                }){ Text(String(index)) }
                .frame(width: 30, height: 30)
                .padding()
            }
        }
        .sheet(isPresented: $presented, content: {
            Text("(index4edit): (data[index4edit-1])")
        })
    }
}
 

Моя проблема в том, что при первом нажатии кнопки, независимо от того, какая кнопка, всегда отображаются первые данные 100 . Причина в том, что данные index4edit не были обновлены при первом нажатии, это всегда 1 так, но почему? Спасибо.

Ответ №1:

Это потому, что представление листа создается при инициализации представления. Когда вы меняете свое состояние, ваше представление не будет воссоздано, потому что ваша переменная состояния не используется в вашем представлении.

Чтобы решить эту проблему, просто используйте свою переменную состояния где-нибудь в коде, например, в этом фиктивном примере

 HStack{
    ForEach(1..<4){ index in
        Button(action: {
            index4edit = index
            presented.toggle()
        }){ Text(String(index)   (index4edit == 0 ? "" : "")) } //<<here is the State used
        .frame(width: 30, height: 30)
        .padding()
    }
}
 

Теперь ваше представление будет повторно отображаться при изменении состояния, следовательно, ваше представление листа будет повторно отображено.

Комментарии:

1. Спасибо. Чтобы избежать его использования где-либо, я делаю его статической переменной.

Ответ №2:

Вы должны настроить index4edit реальный (основанный на 0) индекс, а не индекс 1. Вы также должны использовать data.indices in ForEach вместо ручного ввода диапазона.

 struct TestView: View {
    @State private var data: [Int] = [100, 200, 300]
    @State private var presented: Bool = false
    @State private var index4edit: Int = 0
    
    var body: some View {
        HStack {
            ForEach(data.indices) { index in
                Button(action: {
                    index4edit = index
                    presented.toggle()
                }){ Text(String(index)) }
                .frame(width: 30, height: 30)
                .padding()
            }
        }
        .sheet(isPresented: $presented, content: {
            Text("(index4edit): (data[index4edit])")
        })
    }
}

struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        TestView()
    }
}
 

Комментарии:

1. Спасибо за ответ, но не работает, все равно 100 всегда.

2. @Mandroid как вы создаете TestView ? Я проверил это в предварительном просмотре, и это работает как шарм.

3. @Mandroid Я имел в виду, какой фактический код вы используете. Если бы вы использовали код из моего ответа, это сработало бы, поэтому в вашем коде должна быть другая проблема.

4. Просто скопируйте / вставьте свой код. Эта проблема возникает только при первом нажатии кнопки после запуска.