I have some code which fails to compile. Here is the simplified relevant part:
struct ContentView: View {
@State var currentIndex: Int = 0
var body: some View {
VStack {
ScrollView {
// [...]
}
.scrollPosition(id: $currentIndex)
Button(action: { currentIndex += 1 }) { Text("Next") }
}
}
}
Errors:
>>>> .scrollPosition(id: $currentIndex)
- Cannot convert value of type 'Binding<Int>' to expected argument type 'Binding<(some Hashable)?>'
- Generic parameter 'some Hashable' could not be inferred
Int
is definitely Hashable
.
For some reason the compiler can't figure out that the Binding<Int>
should be acceptable as an argument expecting Binding<(some Hashable)?>
.
The issue seems to be the Optional
part of Binding<(some Hashable)?>
.
Making my state optional - @State var currentIndex: Int? = 0
- solves the issue!
This of course is really annoying, especially if this state is also used in other places which can happily accept a non-optional.
I know I can make it explicitly unwrapped (Int!
) but this is also not ideal, as it still requires unwrapping in some contexts (e.g. if used as part of an .onChange
closure) and overall feels hacky and unnecessary.
Turns out wrapping the argument in Binding(...)
solves the issue without the need of making the @State
optional:
Chang this:
.scrollPosition(id: $currentIndex)
to this:
.scrollPosition(id: Binding($currentIndex))