xyk blog

最近は iOS 開発の記事が多めです。

Swift で UITextField の値の変更を検知する方法

検証環境:
Xcode 12
Swift 5.3

UIControl.Event.editingChanged を使う

let textField = UITextField(frame: .zero)

textField.addTarget(
    self, 
    action: #selector(textDidChange), 
    for: .editingChanged)
@objc func textDidChange(_ textField: UITextField) {
    print(textField.text)
}

UIAction を使う(iOS14以降)

iOS 14から UIControl のサブクラスで、UIAction をイニシャライザや addAction で追加できるようになった。

let textField = UITextField(frame: .zero)

textField.addAction(UIAction() { action in
    guard let text = (action.sender as? UITextField)?.text else { return }
    print(text)
}, for: .editingChanged)

NotificationCenter を使う

let textField = UITextField(frame: .zero)

NotificationCenter.default.addObserver(
    self,
    selector: #selector(textDidChange),
    name: UITextField.textDidChangeNotification,
    object: textField)
@objc func textDidChange(_ notification: Notification) {
    print(textField.text)
}

objectに textField インスタンスを指定することで、この textField の変更のみを検知できる。
objectnilを指定すると、すべての textField の変更を検知するようになる。

KVO(Key Value Observing) を使う

var observers = [NSKeyValueObservation]()
observers.append(textField.observe(\.text, options: [.old, .new]) { (textField, change) in
    guard let newValue = change.newValue else { return }
    print(newValue)
})

UITextFieldDelegate を使う

let textField = UITextField(frame: .zero)

textField.delegate = self
extension ViewController: UITextFieldDelegate {

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let text = (textField.text as NSString?)?.replacingCharacters(in: range, with: string)
        print(text)
        return true
    }
}