Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> iOS

Cách giới hạn UITextField chỉ nhập số trong Swift

Để buộc UITextField chỉ chấp nhận nhập số (digits), có 2 cách chính: cấu hình Keyboard Type trên Storyboard, hoặc lọc ký tự trong Delegate.

Cách 1: Storyboard - Keyboard Type (Đơn giản, UX tốt)

  1. Chọn Text Field trong Storyboard.
  2. Attribute Inspector > Keyboard Type > chọn Number Pad (hoặc Decimal Pad cho số thập phân).
  3. User chỉ thấy bàn phím số – không thể nhập chữ.

Lưu ý: Number Pad không có nút "Return/Done" – cần thêm inputAccessoryView (toolbar) với nút Done để dismiss keyboard.

Cách 2: Delegate - Lọc ký tự (Programmatic validation)


class ViewController: UIViewController, UITextFieldDelegate {
    
    @IBOutlet weak var textField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        textField.delegate = self
        // Tùy chọn: keyboard type vẫn là default hoặc number pad
        textField.keyboardType = .numberPad
    }
    
    func textField(_ textField: UITextField, 
                   shouldChangeCharactersIn range: NSRange, 
                   replacementString string: String) -> Bool {
        
        // Cho phép xóa (backspace = string rỗng)
        if string.isEmpty { return true }
        
        // Chỉ cho phép chữ số 0-9
        let allowedCharacters = CharacterSet.decimalDigits
        let characterSet = CharacterSet(charactersIn: string)
        return allowedCharacters.isSuperset(of: characterSet)
    }
}

Cách 3: Formatter (Cho số có format: currency, decimal...)


let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let currentText = textField.text ?? ""
    guard let stringRange = Range(range, in: currentText) else { return false }
    let updatedText = currentText.replacingCharacters(in: stringRange, with: string)
    
    // Chỉ cho phép nếu parse được thành Number
    return formatter.number(from: updatedText) != nil || updatedText.isEmpty
}

Complete Example (Cách 2 + Toolbar Done)


import UIKit

class ViewController: UIViewController, UITextFieldDelegate {
    @IBOutlet weak var tf: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tf.delegate = self
        tf.keyboardType = .numberPad
        addDoneToolbar()
    }
    
    func addDoneToolbar() {
        let toolbar = UIToolbar()
        toolbar.sizeToFit()
        let doneBtn = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissKeyboard))
        let flexible = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        toolbar.items = [flexible, doneBtn]
        tf.inputAccessoryView = toolbar
    }
    
    @objc func dismissKeyboard() { view.endEditing(true) }
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if string.isEmpty { return true }
        return CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: string))
    }
}

So sánh

CáchƯu điểmNhược điểm
Keyboard TypeUX tốt, không cần code, hệ thống handleKhông có nút Done (cần toolbar), không validate paste
Delegate filterKiểm soát hoàn toàn, validate paste, custom ruleCần code, keyboard vẫn có thể hiện chữ nếu không set type

Best Practice: Kết hợp cả 2: keyboardType = .numberPad + Delegate filter + inputAccessoryView Done toolbar.