iOS development
numpad keyboard
Swift
user interface
programming tutorial

How to add a 'Done' button to numpad keyboard in iOS

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

The iOS number pad is convenient for numeric input, but it does not include a built-in return key. The standard fix is to attach a toolbar above the keyboard and place a Done button on that accessory view so the user can dismiss the keyboard cleanly.

Use inputAccessoryView

Every UITextField and UITextView can display a custom accessory view above the keyboard. For the number pad, this is the normal place to put dismissal controls.

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

This is the most common solution because it works with the system keyboard and avoids building a custom keypad.

Why You Cannot Add a Return Key Directly

A common misunderstanding is that the system number pad can be configured to show a return or done key. In general, that keyboard layout does not expose one. The accessory view is the supported extension point.

That is why the correct solution is not "modify the number pad," but "add controls above it."

Reuse the Toolbar Across Multiple Fields

If several fields use .numberPad, it is worth wrapping the setup in a helper.

swift
1import UIKit
2
3extension UITextField {
4    func addDoneButton(target: Any, action: Selector) {
5        let toolbar = UIToolbar()
6        toolbar.sizeToFit()
7
8        let flex = UIBarButtonItem(
9            barButtonSystemItem: .flexibleSpace,
10            target: nil,
11            action: nil
12        )
13
14        let done = UIBarButtonItem(
15            title: "Done",
16            style: .done,
17            target: target,
18            action: action
19        )
20
21        toolbar.items = [flex, done]
22        inputAccessoryView = toolbar
23    }
24}

Then use it like this:

swift
1override func viewDidLoad() {
2    super.viewDidLoad()
3    amountField.keyboardType = .numberPad
4    amountField.addDoneButton(target: self, action: #selector(dismissKeyboard))
5}

This keeps controller code cleaner and avoids duplicating toolbar construction logic.

Think About the Full Input Flow

The Done button is only one part of the experience. Numeric-entry screens often also need validation, formatting, or navigation to the next field.

If there are several numeric fields, you can replace the single done button with Previous, Next, and Done buttons on the same accessory toolbar. The pattern stays the same; only the actions change.

That is why it helps to think of the accessory view as part of the whole form flow rather than as a one-off keyboard hack.

view.endEditing(true) Is Often Simpler

You can dismiss the active responder directly, but view.endEditing(true) is often the easiest action because it dismisses whichever text input is currently active.

That makes the code more resilient when the screen grows beyond one field.

Common Pitfalls

A common mistake is trying to force the system number pad to include a return key. The proper extension point is the accessory view.

Another issue is calling resignFirstResponder() on the wrong control. Using view.endEditing(true) is often safer.

Developers also sometimes forget accessibility and localization. If you use a custom text title instead of the system .done item, make sure it stays clear to all users.

Summary

  • The iOS number pad has no built-in Done key.
  • Use an inputAccessoryView with a toolbar and Done button.
  • Dismiss the keyboard with view.endEditing(true) or the active field's responder methods.
  • Wrap the setup in an extension if several numeric fields need the same behavior.
  • Treat the accessory view as part of the form's full input flow, not just as a dismissal trick.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.