jellyshoe
jellyshoe

Reputation: 551

Cannot convert value of type 'ClosedRange<Int>' to expected argument type 'Range<Int>'

I have this code:

VStack {
    ForEach(0...2) { i in
        HStack {
            ForEach(0...2) { j in
                Text("test")
            }
        }
    }
}

This gives me the error

Cannot convert value of type 'ClosedRange' to expected argument type 'Range'

on both ForEach calls.

I've seen threads on this error and kind of get it a bit on how the range thing works but not really. I'm wondering how to fix this error.

Upvotes: 32

Views: 31629

Answers (3)

Mojtaba Hosseini
Mojtaba Hosseini

Reputation: 119310

It works if you extend the ForEach with a simple helper initializer like:

extension ForEach where Data == Range<Int>, ID == Int, Content : View {
    public init(_ range: ClosedRange<Int>, @ViewBuilder content: @escaping (Int) -> Content) {
        self.init(range.lowerBound..<(range.upperBound+1), id: \.self, content: content)
    }
}

Demo

Upvotes: 0

Asperi
Asperi

Reputation: 257729

It is possible to use ClosedRange but with different ForEach constructor, providing id, like

    VStack {
        ForEach(0...2, id: \.self) { i in
            HStack {
                ForEach(0...2, id: \.self) { j in
                    Text("test")
                }
            }
        }
    }

Upvotes: 37

Jawad Ali
Jawad Ali

Reputation: 14397

You can use ..< instead of ... for range to be of type Range<Index> instead of ClosedRange<Index>

 VStack {
        ForEach(0..<2) { i in
            HStack {
                ForEach(0..<2) { j in
                    Text("test")
                }
            }
        }
    }

Upvotes: 25

Related Questions