DEV Community

mrcflorian
mrcflorian

Posted on

Managing the Keyboard in SwiftUI: A Comprehensive Tutorial

Managing the appearance and behavior of the keyboard is an essential aspect of creating a seamless user experience in iOS apps. In SwiftUI, while the system manages a lot of this automatically, there are times when you'll want more control.
We've been using all these tips and tricks for our iOS app templates. Let's delve into how you can handle the keyboard in SwiftUI.


1. Introduction to Keyboard Handling

When a user taps on a TextField in SwiftUI, the system automatically displays the keyboard. However, problems can arise if the keyboard obscures the TextField or other important elements of your UI.


2. Responding to Keyboard Appearance

To manage the keyboard's appearance and avoid UI obscurations, you can use the keyboardAdaptive() modifier. But before that, you'll need to observe the keyboard's height.

final class KeyboardResponder: ObservableObject {
    @Published var currentHeight: CGFloat = 0

    var keyboardWillShowNotification = NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)
    var keyboardWillHideNotification = NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)

    init() {
        keyboardWillShowNotification.map { notification in
            CGFloat((notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect)?.height ?? 0)
        }
        .assign(to: \.currentHeight, on: self)
        .store(in: &cancellableSet)

        keyboardWillHideNotification.map { _ in
            CGFloat(0)
        }
        .assign(to: \.currentHeight, on: self)
        .store(in: &cancellableSet)
    }

    private var cancellableSet: Set<AnyCancellable> = []
}
Enter fullscreen mode Exit fullscreen mode

Here, we use Combine's publisher(for:) method to listen for keyboardWillShowNotification and keyboardWillHideNotification notifications.

Now, let's implement the keyboardAdaptive modifier.

struct KeyboardAdaptive: ViewModifier {
    @ObservedObject private var keyboard = KeyboardResponder()

    func body(content: Content) -> some View {
        content
            .padding(.bottom, keyboard.currentHeight)
            .animation(.easeOut(duration: 0.16))
    }
}
Enter fullscreen mode Exit fullscreen mode

Usage:

TextField("Enter text", text: $inputText)
    .modifier(KeyboardAdaptive())
Enter fullscreen mode Exit fullscreen mode

3. Animating with SwiftUI Keyboard

You noticed we added an animation in the keyboardAdaptive modifier. This ensures that when the keyboard appears or disappears, the padding adjustment is animated, providing a smooth experience for the user.


4. Dismissing the Keyboard

In some situations, you might want the user to dismiss the keyboard by tapping outside the TextField or on a "Done" button.

  1. Tapping Outside:
extension View {
    func endEditing() {
        UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}

// Usage:
var body: some View {
    VStack {
        TextField("Enter text", text: $inputText)
    }
    .onTapGesture {
        self.endEditing()
    }
}
Enter fullscreen mode Exit fullscreen mode
  1. Using a Done Button:
var body: some View {
    VStack {
        TextField("Enter text", text: $inputText)
        Button("Done") {
            self.endEditing()
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

5. Keyboard Customization

SwiftUI allows you to customize the keyboard's appearance and behavior by adjusting the TextField's modifiers.

TextField("Enter email", text: $email)
    .keyboardType(.emailAddress)   // Sets the keyboard type
    .autocapitalization(.none)     // Disables auto-capitalization
    .disableAutocorrection(true)   // Disables auto-correction
Enter fullscreen mode Exit fullscreen mode

Conclusion: Managing the keyboard effectively in SwiftUI ensures your users enjoy a smooth and intuitive experience when interacting with your app. By observing keyboard notifications, animating view adjustments, and incorporating some handy extensions, you can create a polished UI that adapts seamlessly to keyboard events.

For more development articles, check out Dopebase programming tutorials.

I hope this tutorial provides you with a solid foundation for managing keyboards in SwiftUI. Happy coding!

Top comments (1)

Collapse
 
tomdotcom profile image
Tom Störmer

Thanks for the content. Just one thing: .assign(to: \.currentHeight, on: self) in KeyboardResponder is causing a retain cycle.

Use assign(to:) instead of assign(to: , on:) to avoid a reference cycle, as mentioned in the docs: developer.apple.com/documentation/...