I am storing a Int value as State in my View. When I press a button the Int increase by one. This is working fine when I print my int value.

I have now a ForEach loop, which iterates based on this Int. When I set my State on 2 by default it works fine at the beginning. However, when I increase that Int my ForEach is not called again.

I understand that State will reload my actual view. Does it only load specific parts?

Here I declare my State:

@State var s_countVenues : Int = 2

This is the ForEach I use. It works at the beginning, however changing s_countVenues does NOT update the view.

ForEach(0..<self.s_countVenues){_ inHStack(spacing: 0){//here comes my view}}

If necessary, here I am increasing my value by one. It works, I printed the changes and if I use it inside a Label, the Label gets updated.

self.s_countVenues += 1

TL:DR:

My Int State is working. I can increase and print it inside a label. However, using it as Statement in ForEach does not call that loop again after changing.

3

Best Answer


from apple docs

extension ForEach where Data == Range<Int>, ID == Int, Content : View {/// Creates an instance that computes views on demand over a *constant*/// range.////// This instance only reads the initial value of `data` and so it does not/// need to identify views across updates.////// To compute views on demand over a dynamic range use/// `ForEach(_:id:content:)`.public init(_ data: Range<Int>, @ViewBuilder content: @escaping (Int) -> Content)}

So, you have to use (as suggested by Apple)

struct ContentView: View {@State var counter = 0var body: some View {VStack {ForEach(0 ..< counter, id:\.self) { i inText("row: \(i.description)")}Button(action: {self.counter += 1}, label: {Text("counter \(counter.description)")})}}}

It is not due to state, it is because you use ForEach constructor with constant Range, it is documented feature, so not supposed to update, so it is not updated. The simplest solution is as following - to use identifier joined to your state. It just indicates for rendering engine that ForEach is new so refresh (Tested with Xcode 11.2 / iOS 13.2)

ForEach(0..<self.s_countVenues){_ inHStack(spacing: 0){//here comes my view}}.id(s_countVenues)

I have silenced it with ', id: .self'