UKey's Labo

テキストフィールド編集でのイベントハンドリング – 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

以下が設定できます。

表示するように設定してあっても、テキストフィールドに文字が入力されていない状態では表示されません。
まぁ、文字入力が無いのにクリアボタンがあってもねぇ、というのは当然かもしれませんが、はじめは「設定したのに表示されねぇ」と、若干パニクりました笑

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
    }
}

一文字入力する毎に動作します。

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
    }    
}