How to dismiss the keyboard in SwiftUI

When dealing with forms and more, it is likely that you would encounter a scenario where you would want to dismiss the keyboard programmatically ie. on click of "Submit" or "Next" button. Without further ado, let's explore a couple of ways to dismiss the keyboard in SwiftUI.

Using App Delegate Methods

One of the easiest way is to use app delegate method and calling the endEditing() on UIApplication. This method will resign the first responder of the view (which, in this case, is the textfield's keyboard).

@State var name : String = ""
    var body: some View {
        VStack {
            TextField("Enter name here", text: $name)
            Button {
                dismissKeyboard() // 1
            } label : {
                Text("Dismiss Keyboard") // 2
            }
        }.padding() // 3
        
    func dismissKeyboard() {
      UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.endEditing(true) // 4
    }
}

Result:

Code Explanation:

  1. Calling the dismiss keyboard method on the click of "Dismiss Keyboard" button.
  2. Setting a label of text "Dismiss Keyboard" of the button.
  3. Adding padding to the view.
  4. Defining dismissKeyboard() function which ends editing on UIApplication.

@FocusState for iOS 15+

The above method requires you to directly interact with the UIApplication method. If you are looking for more SwiftUI-like method to do the same, you can try the FocusState method. The only fallback of this method is that its only available for iOS 15 and later.

@State var name : String = ""
  @FocusState var isFocused : Bool // 1 
    var body: some View {
        VStack {
            TextField("Enter name here", text: $name)
                .focused($isFocused) // 2 
            Button {
                isFocused = false // 3 
            } label : {
                Text("Dismiss Keyboard")
            }
        }.padding()
    }

Result:

Code Explanation:

  1. Defining a @FocusState bool variable. Observe that we are not defining a value to it and rather just assigning it the type of Bool.
  2. Adding the style modifier of to the textfield and assigning it the binding variable of isFocused variable.
  3. Setting the isFocused value to false on the "Dismiss Keyboard" button click.

The above method works when you have one textfield on the screen. Let's take a look at a case when there are multiple textfields on the screen.

	// 1 
    @FocusState var isEmailFocused : Bool 
    @FocusState var isNameFocused : Bool 
    
   // 2 
    @State var email : String = ""
    @State var name : String = ""
    
    var body: some View {
        VStack(spacing: 20) { // 3 
        // 4 
            TextField("Enter name here", text: $name) 
                .focused($isNameFocused)
            TextField("Enter email here", text: $email) 
                .focused($isEmailFocused)
            
            Button("Dismiss Current TextField") { // 5 
                if isNameFocused {
                    isNameFocused = false
                } else if isEmailFocused {
                    isEmailFocused = false
                }
            }

        }.padding()
    }

Result:

Code Explanation:

  1. Defining individual focus state variables for email and name variable
  2. Defining string variables for name and email field
  3. Defining a VStack with spacing set to 15
  4. Showing textfields with text and focus state set to the corresponding variable
  5. Showing a button with text initializer. On tap, the button checks if the isNameFocused is true. If so, it toggles isNameFocused, else if checks if if email is focused and sets it to false.

Congratulations! Today you learned about two ways to dismiss keyboard in SwiftUI - using UIApplication editing method and by using Focus State variable (available for iOS 15 or later) for both single and multiple textfields in the screen. Till then,

Eat. Swift. Swift Anytime. Repeat.

You've successfully subscribed to Swift Anytime
Great! Next, complete checkout to get full access to all premium content.
Error! Could not sign up. invalid link.
Welcome back! You've successfully signed in.
Error! Could not sign in. Please try again.
Success! Your account is fully activated, you now have access to all content.
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.