Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI ForEach based on State int

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)
{_ in
    HStack(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.

like image 615
davidev Avatar asked Nov 25 '25 01:11

davidev


2 Answers

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 = 0
    var body: some View {
        VStack {
            ForEach(0 ..< counter, id:\.self) { i in
                    Text("row: \(i.description)")
                }
            Button(action: {
                self.counter += 1
            }, label: {
                Text("counter \(counter.description)")
            })
        }
    }
}
like image 69
user3441734 Avatar answered Nov 26 '25 16:11

user3441734


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

like image 22
ZeroCooLld Avatar answered Nov 26 '25 18:11

ZeroCooLld