テキストフィールド編集でのイベントハンドリング – UITextFieldDelegate

動作環境
環境 | バージョン |
---|---|
Xcode | 9.4.1 |
iOS | 11.4 |
swift | 4.1.2 |
UITextFieldDelegateの呼ばれるタイミング
以下、7つのタイミングがある。
こんな形でstoryboardを作成してます。
delegateありのほうにUITextFieldDelegateを設定し、
delegateなしのほうは、フォーカスが外れた際の確認用に作成してます。
テキストフィールドをタップ後、入力状態になる前
extension ViewController: UITextFieldDelegate {
/// テキストフィールド入力状態前
///
/// - Parameter textField: 対象のテキストフィールド
/// - Returns: trueで入力可 falseで入力不可
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
print("テキストフィールド入力状態前")
return true
}
}
テキストフィールドをタップ後、入力状態になった後
extension ViewController: UITextFieldDelegate {
/// テキストフィールド入力状態後
///
/// - Parameter textField: 対象のテキストフィールド
func textFieldDidBeginEditing(_ textField: UITextField) {
print("テキストフィールド入力状態後")
}
}
フォーカスが外れる前
この、フォーカスが外れる前と、フォーカスが外れた後の関数は、
キーボードでenterを入力したとき、または、他のテキストフィールドなどにフォーカスが移動したときに実行されます。
extension ViewController: UITextFieldDelegate {
/// フォーカスが外れる前
///
/// - Parameter textField: 対象のテキストフィールド
/// - Returns: trueでフォーカスを外す falseでフォーカスを外さない
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
print("フォーカスが外れる前")
return true
}
}
フォーカスが外れた後
extension ViewController: UITextFieldDelegate {
/// フォーカスが外れた後
///
/// - Parameter textField: 対象のテキストフィールド
func textFieldDidEndEditing(_ textField: UITextField) {
print("フォーカスが外れた後")
}
}
リターンキー入力後
extension ViewController: UITextFieldDelegate {
/// リターンキー入力時
///
/// - Parameter textField: 対象のテキストフィールド
/// - Returns: trueでリターン実行 falseでリターンを無視
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
print("リターン入力時")
// キーボードを閉じる
textField.resignFirstResponder()
// これでも閉じる
// textField.endEditing(true)
return true
}
}
ここで、textField.resignFirstResponder()
を実行、もしくは、
textField.endEditing(true)
を実行してやると、開いていたキーボードが閉じます。
クリア前
クリアーボタンを使用して、テキストをクリアする場合、
もしくは、「Clear when editing begin」が有効で、フォーカスが当たった際にテキストフィールドが
クリアされた場合に、動作します。
extension ViewController: UITextFieldDelegate {
/// クリア前
///
/// - Parameter textField: 対象のテキストフィールド
/// - Returns: trueでクリア実行 falseでクリアしない
func textFieldShouldClear(_ textField: UITextField) -> Bool {
print("クリア前")
return true
}
}
ちなみに、クリアボタンはStoryboard上で設定できます。
Clear Button
以下が設定できます。
- Never Appears : クリアボタンを表示しません
- Appears while editing : テキストフィールド編集中にのみ表示します
- Appears unless editing : テキストフィールドにフォーカスが当たっていない場合のみ表示します
- Is always visible : 常に表示します
表示するように設定してあっても、テキストフィールドに文字が入力されていない状態では表示されません。
まぁ、文字入力が無いのにクリアボタンがあってもねぇ、というのは当然かもしれませんが、はじめは「設定したのに表示されねぇ」と、若干パニクりました笑
Clear when editing begins
こちらのチェックボックスにチェックを入れると、テキストフィールドに文字入力後、
一旦フォーカスを外し、再度テキストフィールドにフォーカスを当てた際に、入力していた文字がクリアされます。
上記にも記載したとおり、この場合もtextFieldShouldClear
が走ります。
編集時
extension ViewController: UITextFieldDelegate {
/// 編集中
///
/// - Parameter textField: 対象のテキストフィールド
/// - Parameter range:
/// - Parameter string:
/// - Returns:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
print("編集中")
print("textField : \(textField)")
print("range : \(range)")
print("string : \(string)")
return true
}
}
一文字入力する毎に動作します。
range(location: length:)
: locationに入力した文字の位置、lengthに入力した文字数が入ります。 半角英数字を入力中はlengthに0が入りますが、英語で予測変換で文字入力した際、日本語入力等、入力後に変換などを行い、Enterで確定するような文字の場合には、lengthには文字数が入ります。string
: 入力した文字が入ります。rangeと同じような形で、半角英数字入力時はキーボードを入力するたびに文字が入りますが、日本語等入力時には、入力が確定した時点での文字列が入ります。
UITextField入力後、Enterでキーボードを閉じる
特に設定なしで、キーボード表示はできるようですが、
キーボードの閉じ方がわからなかったので、調べました。
UITextFieldDelegateを実装するだけで実現できるので、簡単です。
class KeyboardCloseExampleViewController: UIViewController {
// 今回ターゲットとなるテキストフィールド
@IBOutlet weak var tField: UITextField!
override func viewDidLoad() {
// delegateを設定する
tField.delegate = self
}
}
extension KeyboardCloseExampleViewController: UITextFieldDelegate {
/// キーボードリターンで閉じる
///
/// - Parameter textField: 画面項目
/// - Returns: 閉じるtrue
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// キーボードを閉じる
textField.resignFirstResponder()
// これでもOK
// textField.endEditing(true)
return true
}
}