'Wrong counting while using ForEach in SwiftUI

I have found this question while scouring for some info for my project. It was unanswered, but I used it as an answer to my problem after a little fix '^^

The question:

how to change from default "2 cups" to 1 cup. ? My coffeAmmount is 1 so as I understand $0 should also be 1 in Text view. But its showing default as 2. Can someone explain ?

thanks.!!

The code:

import SwiftUI

struct ContentView: View {
     
@State private var coffeAmmount = 1
    
var body: some View {
     Section(header: Text("Daily coffe intake")
                        .font(.headline)){
                            Picker("How many cups", selection: $coffeAmmount){
                                ForEach(1..<21){
                                    Text($0 > 1 ? "\($0) cups" : "\($0) cup")
                                }
                            }
                    }
}
}

The original topic: https://www.hackingwithswift.com/forums/100-days-of-swiftui/betterrest-day-28-challenge-2-how-to-create-a-simple-integer-picker/587



Solution 1:[1]

You just have to set

coffeAmmount

to 0:

@State private var coffeAmmount = 0

SwiftUI treats this variable as a pointer to the place in range you created with use of ForEach. So the ForEach range is (1, 2, 3, ..., 20) but their indexes are 0 for 1; 1 for 2 etc. Swift, as many of the programming languages, starts counting the indexes and other stuff from 0 not from 1 by default.

By setting coffeAmmount to 0 you actually show Xcode that you want the value from the index (place in range you created) "branded" 0 which value is 1 :)

Hope that helps people with the similar problem, since the question was asked 2 years ago.

Solution 2:[2]

The other fix would be to make it an array, and not a range. This may be a bit more intuitive for some as your are always dealing with the numbers you actually set in the ForEach like this:

struct CoffeeView: View {
    @State private var coffeAmmount = 1
    var body: some View {
        Picker("How many cups", selection: $coffeAmmount){
            // make this an Array and the value matches
            ForEach(Array(1..<21), id: \.self){ cup in
                Text(cup > 1 ? "\(cup) cups" : "\(cup) cup")
            }
        }
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Swantewit
Solution 2 Yrb