Soy nuevo en programación y SwiftUI y estoy haciendo esta aplicación donde los usuarios pueden seleccionar estos botones etiquetados como A-D. Pueden elegir más de 1, y espero que cuando hagan clic en el botón, el color de fondo cambie de gris a verde. Sin embargo, si reemplazo "// Aquí" en el código en la parte inferior con

Data.Selected = true
Data.Colour = .green

Recibo un error que dice "No se puede asignar a la propiedad: 'Datos' es una constante 'let'". Entiendo lo que eso significa, pero no sé cómo cambiar los datos a var. Traté de escribir var delante de "Datos en", pero recibí este error en su lugar "Las declaraciones consecutivas en una línea deben estar separadas por ';'". ¿Hay alguna forma de modificar directamente Data / ButtonsData? ¿O hay una solución alternativa?

struct Buttons: Hashable {
    var Crit: String
    var Selected: Bool
    var Colour: Color
}

var ButtonsData = [
    Buttons(Crit: "A", Selected: false, Colour: Color(.systemGray4)),
    Buttons(Crit: "B", Selected: false, Colour: Color(.systemGray4)),
    Buttons(Crit: "C", Selected: false, Colour: Color(.systemGray4)),
    Buttons(Crit: "D", Selected: false, Colour: Color(.systemGray4))
]

struct CritView: View {
    
    @Binding var CritBoard: Bool
    @Binding var BackgroundColor: Color
    
    var body: some View {
        ZStack(alignment: .topLeading) {
            
            ScrollView(.vertical, showsIndicators: false) {
                HStack(spacing: 15) {
                    ForEach(ButtonsData, id: \.self) { Data in
                        Button(action: {
                          // HERE
                        }) {
                            Text(Data.Crit)
                                .font(.system(size: 30))
                        }
                        .frame(width: 65, height: 55)
                        .background(Data.Colour)
                        .cornerRadius(10)
                    }
                }
                .padding(.top, 50)
            }
            .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height/8)
            .padding(.bottom, UIApplication.shared.windows.first?.safeAreaInsets.bottom)
            .background(Color(.white))
            .cornerRadius(25)
            
            Button(action: {
                self.CritBoard.toggle()
                self.BackgroundColor = .white
            }) {
                Image(systemName: "xmark").foregroundColor(.black)
            }.padding(25)
        }
    }
}
1
Daniel Ho 23 jun. 2020 a las 17:12

2 respuestas

Bueno, no creo que mucha gente realmente tenga el mismo problema / similar, pero este es mi código de trabajo. El código usa tanto la respuesta de @ Aspersi como el código en un artículo de Hacking with Swift. (puede que no sea el código más simplificado, pero al menos funciona en este momento)

ForEach(Array(ButtonsData.enumerated()), id: \.element) { i, Data in
    Button(action: {
        self.AllData[i].Selected.toggle()
        if self.AllData[i].Selected == true {
            self.AllData[i].Colour = .green
        } else {
            self.AllData[i].Colour = Color(.systemGray4)
        }
    }) {
        Text(Data.Crit)
            .font(.system(size: 30))
    }
    .frame(width: 65, height: 55)
    .background(self.AllData[i].Colour)
    .cornerRadius(10)
}

Código completo a continuación

struct Buttons: Hashable {
    var Crit: String
    var Selected: Bool = false
    var Colour: Color
}

var ButtonsData = [
    Buttons(Crit: "A", Selected: false, Colour: Color(.systemGray4)),
    Buttons(Crit: "B", Selected: false, Colour: Color(.systemGray4)),
    Buttons(Crit: "C", Selected: false, Colour: Color(.systemGray4)),
    Buttons(Crit: "D", Selected: false, Colour: Color(.systemGray4))
]

struct CritView: View {
    
    @Binding var CritBoard: Bool
    @Binding var BackgroundColor: Color
    
    @State private var AllData = ButtonsData
    
    var body: some View {
        ZStack(alignment: .topLeading) {
            
            ScrollView(.vertical, showsIndicators: false) {
                HStack(spacing: 15) {
                    ForEach(Array(ButtonsData.enumerated()), id: \.element) { I, Data in
                        Button(action: {
                            self.AllData[i].Selected.toggle()
                            if self.AllData[i].Selected == true {
                                self.AllData[i].Colour = .green
                            } else {
                                self.AllData[i].Colour = Color(.systemGray4)
                            }
                        }) {
                            Text(Data.Crit)
                                .font(.system(size: 30))
                        }
                        .frame(width: 65, height: 55)
                        .background(self.AllData[i].Colour)
                        .cornerRadius(10)
                    }
                }
                .padding(.top, 50)
            }
            .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height/8)
            .padding(.bottom, UIApplication.shared.windows.first?.safeAreaInsets.bottom)
            .background(Color(.white))
            .cornerRadius(25)
            
            Button(action: {
                self.CritBoard.toggle()
                self.BackgroundColor = .white
            }) {
                Image(systemName: "xmark").foregroundColor(.black)
            }.padding(25)
        }
    }
}
0
Daniel Ho 24 jun. 2020 a las 03:50

Aquí hay una posible solución: cree una matriz de tuplas de índice / valor y modifique sus datos en el contenedor original por índice:

ForEach(Array(ButtonsData.enumerated()), id: \.element) { i, Data in
    Button(action: {
      ButtonsData[i].Selected = true
      ButtonsData[i].Colour = .green
    }) {
        Text(Data.Crit)
            .font(.system(size: 30))
    }
    .frame(width: 65, height: 55)
    .background(Data.Colour)
    .cornerRadius(10)
}
1
Asperi 23 jun. 2020 a las 14:21