iOS
Swift
Numpad
Done Button
Programming

How to add Done button to Numpad in iOS using Swift?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The iOS number pad does not include a built-in Done key, so users can get stuck with the keyboard onscreen unless your app provides another way to dismiss it. The standard fix is to attach a toolbar above the keyboard and put a Done button on that toolbar.

In UIKit, this is done through the text field or text view's inputAccessoryView. Once that accessory view is attached, the Done button can call resignFirstResponder() to dismiss the numpad cleanly.

The Basic Approach

For a UITextField, set keyboardType to a numeric keyboard and attach a UIToolbar as the accessory view:

swift
1import UIKit
2
3final class ViewController: UIViewController {
4    @IBOutlet private weak var amountField: UITextField!
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8
9        amountField.keyboardType = .numberPad
10        amountField.inputAccessoryView = makeDoneToolbar()
11    }
12
13    private func makeDoneToolbar() -> UIToolbar {
14        let toolbar = UIToolbar()
15        toolbar.sizeToFit()
16
17        let flex = UIBarButtonItem(
18            barButtonSystemItem: .flexibleSpace,
19            target: nil,
20            action: nil
21        )
22
23        let done = UIBarButtonItem(
24            barButtonSystemItem: .done,
25            target: self,
26            action: #selector(doneTapped)
27        )
28
29        toolbar.items = [flex, done]
30        return toolbar
31    }
32
33    @objc private func doneTapped() {
34        amountField.resignFirstResponder()
35    }
36}

This is the most common and reusable solution.

Why inputAccessoryView Is the Right Tool

The accessory view sits just above the keyboard and follows the first responder automatically. That makes it a better choice than placing a separate button elsewhere on the screen when the only goal is keyboard dismissal.

It also matches normal iOS behavior for forms where the keyboard type lacks a built-in action key.

Supporting Multiple Fields

If several numeric fields need the same toolbar, you can attach the same accessory view to each one and resign the current first responder generically:

swift
1final class ViewController: UIViewController {
2    @IBOutlet private weak var ageField: UITextField!
3    @IBOutlet private weak var priceField: UITextField!
4
5    override func viewDidLoad() {
6        super.viewDidLoad()
7
8        let toolbar = makeDoneToolbar()
9
10        ageField.keyboardType = .numberPad
11        priceField.keyboardType = .decimalPad
12
13        ageField.inputAccessoryView = toolbar
14        priceField.inputAccessoryView = toolbar
15    }
16
17    private func makeDoneToolbar() -> UIToolbar {
18        let toolbar = UIToolbar()
19        toolbar.sizeToFit()
20
21        toolbar.items = [
22            UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
23            UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneTapped))
24        ]
25
26        return toolbar
27    }
28
29    @objc private func doneTapped() {
30        view.endEditing(true)
31    }
32}

Using view.endEditing(true) is convenient when you do not want to track which specific field is active.

Works for UITextView Too

The same idea also works for text views:

swift
textView.keyboardType = .numberPad
textView.inputAccessoryView = makeDoneToolbar()

The dismissal action can still call view.endEditing(true) or textView.resignFirstResponder().

Choosing the Keyboard Type

If the user needs decimals or phone-style input, remember that .numberPad, .decimalPad, and .phonePad are different keyboards.

The Done toolbar solution works with all of them because it is not tied to a specific key layout. That is one reason it is better than trying to simulate a missing key on the keyboard itself.

Common Pitfalls

The biggest pitfall is looking for a property that magically adds a Done key to .numberPad. UIKit does not provide a one-line built-in switch for that keyboard type.

Another common issue is forgetting to call sizeToFit() on the toolbar. Without that, the accessory view may not size itself correctly.

Developers also sometimes target the Done button at the wrong object or forget the @objc method, which means tapping the button does nothing.

Finally, remember that keyboard dismissal is only one part of the UX. If the field needs validation or formatting, do that separately instead of overloading the Done button action with unrelated logic.

Summary

  • The iOS number pad has no built-in Done key.
  • The standard solution is a UIToolbar assigned to inputAccessoryView.
  • Put a .done bar button item on the toolbar and dismiss the keyboard with resignFirstResponder() or view.endEditing(true).
  • The same approach works for UITextField and UITextView.
  • Use this pattern for .numberPad, .decimalPad, and similar keyboards that lack a built-in dismissal action.

Course illustration
Course illustration

All Rights Reserved.