UITextFieldを空の状態からデリートキーを検出する
文字入力の検出
まずUITextField
において文字入力を検出するには主に2つの方法がある。
一つはUITextFieldDelegate
を準拠し、textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool
を用いる方法。もう一つはUIControl
にあるaddTarget(_:action:for:)
を以下のように書いて、テキストの内容が変更したタイミングで#selector
で指定した関数でハンドリングする。
let textField = UITextField() textField.addTarget(self, action: #selector(textFieldDidChangeText(_:)), for: .editingChanged)
自分もいずれかの方法で文字入力のハンドリングをしていたが、ある時一つの問題を発見した。それは、テキストが空の状態からデリートキーの入力を検出できないことだ。
自分が直面したケースとしては、複数のテキストフィールドを用いてPINの入力する画面である。1桁入力するごとに次のテキストフィールドに移動し、デリートキーを入力すれば前のテキストフィールドに戻るといったものを実装しようとしたところ問題を見つけた。
今フォーカスされているテキストフィールドには文字がないので、デリートキーを検出できなかった。
テキストが空の状態からデリートキーを検出する
初めに紹介した2つの方法では無理なので調べていたら解決法を見つけた。UITextField
においてデリートキーはUIKeyInput
にあるdeleteBackward()
を呼ぶことで入力しているらしい。つまりUITextField
を継承したクラスを作成し、deleteBackward()
をオーバライドして扱えるようにすればいい。そして、独自のDelegateを用意しそのタイミングで外のクラスに処理を委譲すればいい。具体的には以下のようなコードになる。
protocol CustomTextFieldDelegate: class { func didDeleteBackward(_ textField: CustomTextField) } class CustomTextField: UITextField { weak var deletionDelegate: CustomTextFieldDelegate? override func deleteBackward() { super.deleteBackward() deletionDelegate?.didDeleteBackward(self) } }
また、これを使いframeworkにしたものサンプル付きでgithubに上げた。(簡単とは言え初めてframeworkを作った) github.com