How to add a ‘Done’ button to a numberPad in Swift

The best way to add a ‘Done‘ button to a numberPad, which doesn’t have it by default,  is to extend UITextField. Three steps:

1. set the keyboard type for your UITextField in your viewController subclass:

e.g. myTextField.keyboardType = UIKeyboardType.numberPad

2. save the code below the line as  ‘UITextField+Extensions.swift’ and add to your project.

3. After this, if you select any UITextField in the storyboard editor, there will be a new item under the ‘Attributes Inspector’ for that UITextField, where you can set ‘Done Access…’ On, Off or default. Choose ‘On’ if you want the ‘Done’ button to show up.

import Foundation

import UIKit

extension UITextField{

       @IBInspectable var doneAccessory: Bool{


            return self.doneAccessory


        set (hasDone) {

            if hasDone{






    func addDoneButtonOnKeyboard()


        let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))

        doneToolbar.barStyle = .default


        let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)

        let done: UIBarButtonItem = UIBarButtonItem(title: “Done”, style: .done, target: self, action: #selector(self.doneButtonAction))


        let items = [flexSpace, done]

        doneToolbar.items = items



        self.inputAccessoryView = doneToolbar



    @objc func doneButtonAction()





how to do validation of a UITextField, while still being edited

If you want to add validation to an instance of UITextField, while editing is still going on, there are a few things you need to do.

Step 1:

Make the viewController adopts UITextFieldDelegate in the class declaration

e.g. class myViewController: UIViewController, UITextFieldDelegate {…}

Step 2:

Set the viewController as the delegate for each of your UITextFields, e.g. in the viewController’s viewDidLoad() function. ‘self’ refers to the viewController.

e.g. myTextField.delegate = self

Step 3:

You need to include the following optional delegate function within your viewController class:

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {…}

The important thing to note is that you can’t just check if the UITextField.text is nil or empty when unwrapped, because that won’t work if the UITextField is currently being edited. For that you need to check the UITextField.text + the replacementString.


Note: Since UITextField.text can be nil, safer to set a variable using the nil coalescing operator, then concatonate with the string

e.g. let currentTextInTextField = textField.text ?? “”

then you can do your validation against (currentTextInTextField+string)

Step 4:

return false if your validation fails, or true if it succeeds.