State when a property of a custom object changes

Viewed 94

I have an Object like this (simplified):

struct BoxModel: Codable, Identifiable, Hashable {
    var id: Int
    var number: Int
}

I have a two dimensional array of these:

@State private var matrix = generate()

where generate creates a 2D array of the objects: [[BoxModel]]. I then display them in a grid. The grid is pretty complex but here's a very simplified form:

LazyVGrid(columns: columns, spacing: 0 ) {
    ForEach(1...9, id: \.self) { j in
         Text("\(getModel(j).number)")
    }
}

Where getValue gets the item from the array that corresponds to the grid location. Since the grid is complex, I need to do some arithmetic in a separate function to do this.

Below this is a button. When the user taps it, it changes the number property of one of the objects in the array. However, the number doesn't update. I thought it would since the array is a @State property.

Is there a way to make it update?

Here's an extremely simplified form of the ContentView:

struct ContentView: View {

@State private var matrix = generate()


var body: some View {
    NavigationView {
        GeometryReader { geometry in
            ScrollView {
                VStack {

                    let columns = [GridItem(.fixed(50), spacing: 0),
                                     GridItem(.fixed(50), spacing: 0),
                                     GridItem(.fixed(50), spacing: 0)]
                    

                    LazyVGrid(columns: columns, spacing: 0 ) {
                        ForEach(1...9, id: \.self) { j in
                            Text("\(getModel(j).number)")
                        }
                    }
                    .padding()
                    Button {
                        var model = getModel(0)
                        model.number = 5
                    } label: {
                        Text("Click Me")
                    }
                }
            }
        }
    }
}


func getModel(_ i: Int) -> BoxModel {
    // very simplified
    return matrix[0][i]
}
1 Answers

In summary, the code in your Button closure is creating a new Object which is different/not related to the matrix variable. So updating the new Object won't affect the @State variable.

Change the code in your Button action closure, from:

var model = getModel(0)
model.number = 5

to

if let index = matrix[0].firstIndex(of: getModel(1)) {
    matrix[0][index].number = 5
}

The goal is to make sure you're updating/changing the @State property itself.

Related