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

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

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
50
2

Ответы:

Вы должны настроить index4edit как реальный индекс (отсчитываемый от 0), а не индекс + 1. Вы также должны использовать data.indices в 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()
    }
}

Решено

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

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

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()
    }
}

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