UITextField
iOS Development
Swift
Input Validation
Numeric Input

Allow only Numbers for UITextField input

Master System Design with Codemia

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

Introduction

Restricting UITextField input to numbers is common for OTP, account ids, and quantity fields. The keyboard type helps users but does not enforce correctness, because paste and hardware keyboards can still insert invalid characters. A reliable solution validates each proposed text change and applies business rules to the full candidate value.

Keyboard Type Improves UX but Is Not Security

Start with a numeric keyboard to reduce invalid typing friction.

swift
numberField.keyboardType = .numberPad

This changes the on screen keyboard only. It does not block non digit text from paste operations or external input devices.

Enforce Numeric Input in Delegate

Use UITextFieldDelegate and validate proposed edits in shouldChangeCharactersIn.

swift
1import UIKit
2
3final class ViewController: UIViewController, UITextFieldDelegate {
4    @IBOutlet private weak var numberField: UITextField!
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8        numberField.delegate = self
9        numberField.keyboardType = .numberPad
10    }
11
12    func textField(_ textField: UITextField,
13                   shouldChangeCharactersIn range: NSRange,
14                   replacementString string: String) -> Bool {
15        if string.isEmpty { return true } // backspace
16
17        let digits = CharacterSet.decimalDigits
18        return string.unicodeScalars.allSatisfy { digits.contains($0) }
19    }
20}

This blocks direct insertion of non digit characters.

Validate Full Candidate String

Character checks alone are not enough for max length or formatting rules. Build the candidate full text first.

swift
1func textField(_ textField: UITextField,
2               shouldChangeCharactersIn range: NSRange,
3               replacementString string: String) -> Bool {
4
5    guard let current = textField.text,
6          let swiftRange = Range(range, in: current) else {
7        return false
8    }
9
10    let candidate = current.replacingCharacters(in: swiftRange, with: string)
11
12    if candidate.count > 6 { return false }  // example rule
13    if candidate.isEmpty { return true }
14
15    return candidate.allSatisfy { $0.isNumber }
16}

This handles insertion, deletion, replacement, and paste consistently.

Decimal and Signed Inputs

If your field should allow decimals or negatives, use explicit validation logic instead of simple digit filtering.

swift
1func isValidDecimal(_ value: String) -> Bool {
2    if value.isEmpty { return true }
3    let pattern = "^-?[0-9]*([.][0-9]*)?$"
4    return value.range(of: pattern, options: .regularExpression) != nil
5}

For international users, use locale aware decimal separators rather than hardcoded dot.

Maintain Raw and Display Values Separately

Sometimes you want formatted display while storing raw digits. Keep these separate to avoid data corruption.

swift
func digitsOnly(_ text: String) -> String {
    String(text.filter { $0.isNumber })
}

Use raw digits for API requests and persistence. Apply formatting only in UI rendering.

SwiftUI Equivalent

In SwiftUI, enforce numeric rules in a custom binding setter.

swift
1import SwiftUI
2
3struct OtpView: View {
4    @State private var otp = ""
5
6    var body: some View {
7        TextField("Code", text: Binding(
8            get: { otp },
9            set: { otp = String($0.filter { $0.isNumber }.prefix(6)) }
10        ))
11        .keyboardType(.numberPad)
12    }
13}

This mirrors UIKit behavior without a delegate method.

Accessibility and Error Feedback

Silently rejecting characters can confuse users, especially with assistive technologies. For strict forms, provide clear feedback such as inline helper text or an accessibility announcement when input is rejected.

If you require a fixed length code, indicate progress explicitly so users know why additional digits are not accepted.

Form Validation Strategy

For high-risk fields such as payment amounts or account numbers, combine UITextField filtering with server-side validation and domain-level parsing. UI rules improve user experience, but backend validation is the final authority for correctness and fraud resistance.

Testing Real Device Input Paths

Run validation tests with hardware keyboard, paste actions, and accessibility input modes. Numeric filtering that works in simulator typing can still fail in real user input paths.

Common Pitfalls

A frequent pitfall is relying only on .numberPad. This does not prevent non numeric paste.

Another issue is forgetting backspace handling by rejecting empty replacement strings, which breaks deletion.

Teams also validate only inserted characters and ignore full candidate length and formatting rules.

Summary

  • Use .numberPad for better typing UX, but enforce input with validation logic.
  • Validate full candidate text, not only incoming characters.
  • Handle paste, delete, and max length rules explicitly.
  • Add locale aware parsing for decimal input when needed.
  • Revalidate numeric fields in domain or server layers for correctness.

Course illustration
Course illustration

All Rights Reserved.