I'm curious, has anyone seen this before, or do they know how to solve it? I have a situation where editing a textfield that's in a NavigationStack always pops the text cursor to the end of the field on every keystroke. I suspect it has something to do with SwiftUI's management of views and state, but I am not spotting anything unusual that I might be doing, other than the index lookup in the navigationDestination part. I don't understand why that would be a problem.
Here's some pretty minimal code demonstrating the problem (just try correcting the well-known Shakespeare quote):
struct CursorResetting: View {
struct Record: Identifiable {
var string = ""
var id = UUID()
}
@State var path = NavigationPath()
@State private var records = [
Record(string: "To be and not to be"),
Record(string: "That begs the question")
]
var body: some View {
NavigationStack(path: $path) {
Form {
List {
ForEach(records) { record in
NavigationLink(value: record.id) {
Text(record.string)
}
}
}
}
.navigationDestination(for: UUID.self) { id in
let index = records.firstIndex { $0.id == id }
if let index {
Form {
TextField("Value", text: $records[index].string)
}
} else {
Text("Invalid ID")
}
}
}
}
}
This is a known thing, and the reason why you can't use a Binding
type with navigationDestination
.
Binding
triggers the View
to redraw and it resets everything in the body
including the navigationDestination
modifier.
You have to use NavigationLink(destination:, label:)
import SwiftUI
struct CursorResettingView: View {
struct Record: Identifiable {
var string = ""
var id = UUID()
}
@State var path = NavigationPath()
@State private var records = [
Record(string: "To be and not to be"),
Record(string: "That begs the question")
]
var body: some View {
NavigationStack(path: $path) {
Form {
List {
ForEach($records) { $record in
NavigationLink {
Form {
TextField("Value", text: $record.string)
}
} label: {
Text(record.string)
}
}
}
}
.navigationDestination(for: UUID.self) { id in
//Use this for `View`s that don't use `Binding` type as argument.
}
}
}
}
struct CursorResettingView_Previews: PreviewProvider {
static var previews: some View {
CursorResettingView()
}
}
Anything that uses an array's index
is generally considered unsafe with SwiftUI so "solutions" that depend on it will be inherently fragile.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With