Search code examples
swiftuiswiftui-foreach

How do I keep a counter of a nested loop?


I have a 2D array that I need to traverse through, where each inner looping adds a new View. I've tried having a @State variable and increasing it by one on onAppear, like in this simplified example:

struct ContentView: View {
    @State private var counter = -1
    
    var body: some View {
        ForEach(0...2, id: \.self) { i in
            ForEach(0...2, id: \.self) { j in
                Text("Iteration #\(counter)")
                    .onAppear {
                        counter += 1
                    }
            }
        }
    }
}

But it gives me nine TextViews with the text "Iteration #8". How can I make it show each value from 0 to 8 like a counter would?


Solution

  • ForEach is really just for constructing views that require repeated use of the same models. In this case, I separated out the incrementing logic into a function. You can then use the result of this function to construct a view that creates as many text fields as desired. Note that the ForEach is counting up to the return value of our iterateCounter function.

    This may not be the exact math you need, but you can modify the numbers to make it work for you!

     struct ContentView: View {
        @State private var counter = -1
        
        var count: Int {
            iterateCounter()
        }
        
        var body: some View {
            ScrollView {
                ForEach(0...count, id: \.self) { i in
                    Text("Iteration #\(i)")
                }
            }
        }
        
        func iterateCounter() -> Int {
            var count1 = 0
            var count2 = 0
            
            for _ in 0...2 {
                count1 += 1
                for _ in 0...2 {
                    count2 += 2
                }
            }
            return count1 + count2
        }
    }