FocusState / SwiftUI

Short tutorial on how to navigate between TextFields using FocusState

Sullivan De Carli
Swift Productions
3 min readOct 12, 2022

--

iPhone opening a form with a keyboard with the SwiftUI logo

Difficulty: Beginner | Easy | Normal | Challenging

Environment : Xcode 14, iOS 16 & SwiftUI

Full code at the end of the article

Introduction

iOS 15 introduced a new SwiftUI property wrapper called FocusState. It is an helpful API to track which View is receiving user input.

For the purpose of this tutorial, we will create a SwiftUI Form composed of 3 TextField. We will then implement the FocusState to navigate between fields using the keyboard, we will also add a focus on the first fields upon screen launch.

Create new Xcode Project

Open Xcode > App template > SwiftUI Life Cycle and call it textfieldfocus

Make sure your project is running on iOS 15+

Creating the Form

Heads to the ContentView.swift file and add the followings State so we can observe the user entries in the TextField:

@State private var firstName = ""@State private var lastName = ""@State private var password = ""

Then, add the Form, replace the current boilerplate code inside the body variable by this SwiftUI Form:

Form {TextField("First name", text: $firstName).disableAutocorrection(true).submitLabel(.next)TextField("Last name", text: $lastName).textContentType(.familyName).disableAutocorrection(true).submitLabel(.next)SecureField("Password", text: $password).submitLabel(.done)}

Implement FocusState

Now that we have the user interface, we can implement our focus so that users can navigate between TextField. Add the followings FocusState and enum case over the body variable:

@FocusState private var focusedField: FormField?enum FormField {case firstName, lastName, password}

To add this ability in the keyboard, we just need to use the .onSubmit modifier. Add it right after the last Form graph:

.onSubmit {  switch focusedField {    case .firstName:     focusedField = .lastName   case .lastName:    focusedField = .password.     case .password:    focusedField = nil  print(“Name and surname filled: \(firstName),\(lastName)”)  default:     focusedField = nil  }}

And now, we only need to add the focused as a modifier with our TextFields such as follows:

TextField(“First name”, text: $firstName).disableAutocorrection(true).submitLabel(.next).focused($focusedField, equals: .firstName)TextField(“Last name”, text: $lastName).textContentType(.familyName).disableAutocorrection(true).submitLabel(.next).focused($focusedField, equals: .lastName)SecureField(“Password”, text: $password).submitLabel(.done).focused($focusedField, equals: .password)

Also, with the .onAppear modifier, you can put the focus on the first TextField, this way, upon launch of the screen, the user will be bring to the first TextField.

Add this after the .onSubmit modifier:

.onAppear { focusedField = .firstName }

Great, now that is done, we can run our application and navigate between TextField with the keyboard. Also, when the App is launched, we are bring directly to the username TextField and the keyboard is popping up.

Xcode with the simulator running
Final result

I’m always happy to have a chat and collaborate at hello@sullivandecarli.com. Consider subscribing to enjoy unlimited access to my articles and all of Medium through my referral link:

Full code below:

--

--

Sullivan De Carli
Swift Productions

Consultant in iOS Dev at Deloitte. I write about Design & App development. Let’s have a chat at hello@sullivandecarli.com