Common examples of this in action tend to use custom enum to allow transition between the fields in the form however in most cases the fields of the form naturally belong to the fields in your models. Therefore it is possible to use KeyPath As the target value, and in fact, since the value only needs to match the Hashable we can even use
AnyKeyPath As a type so that we can deal with targeting across multiple domains spanning more than one sample.
struct ContentView: View @State var project = Project() @FocusState var focus: AnyKeyPath? var body: some View Form TextField("Name", text: $project.name) .focused($focus, equals: Project.name) TextEditor(text: $project.body) .focused($focus, equals: Project.body)
Adding a submit button to the form allows us to verify and if necessary target the user in a field that lacks value.
Button("Submit") guard project.name != "" else focus = Project.name return guard project.body != "" else focus = Project.body return
In addition, we can add an
onAppear(perform:) Operation to from so that we can also move the focus as soon as the form appears on the screen.
.onAppear guard project.name != "" else focus = Project.name return guard project.body != "" else focus = Project.body return
Response to focus changes can be useful as well, in this example we can force the focus back to
name Field if not defined by adding
.onChange(of: focus) newValue in if project.name == "" focus = Project.name