元柔道整復師エンジニアBlog

- 元柔道整復師エンジニアBlog -

『 エンジニアをリングする。』

【Swift】 TextFieldをタップした時に全選択できるようにする

環境

目的

TextFieldをタップした時に、TextFieldの値が存在する場合において全選択をできるように設定する。

準備

  • ViewControllerにUITextFieldDelegateを設定する。
class ViewController: UIViewController, UITextFieldDelegate {

    // UITextFieldの定義
    @IBOutlet weak var myTextField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // UITextFieldDelegateの設定
        self.urlTextField.delegate = self
    }
    
    func textFieldDidBeginEditing(_ textField: UITextField) {
        // ここに本処理を記述していく
    }

}

処理

1. TextFieldの選択範囲を指定する方法:textRange(from: UITextPosition, to: UITextPosition)
func textFieldDidBeginEditing(_ textField: UITextField) {

    // TextFieldの選択範囲を最初から最後まで(全選択)に指定する
    textField.selectedTextRange = textField.textRange(
        from: textField.beginningOfDocument,
        to: textField.endOfDocument) 
}
2. TextField内の文字列を選択状態にする方法:selectAll(sender: Any?)
func textFieldDidBeginEditing(_ textField: UITextField) {

    // nilチェック
    if textField != self.urlTextField {
        return
    }
    
    // TextField内の文字列を選択状態にする
    textField.selectAll(self.textField.text)
}

問題

2回に1度しか全選択の状態にならない

1回目にTextFieldをタップした時は全選択ができているが、再度繰り返し同じ動作をすると全選択とならない。

再現
  1. シュミレータ起動後、対象のTextFieldを選択(タップ)する。
  2. キーボードが上がり、TextFieldが全選択される。
  3. 確認後、TextField以外の部分を選択し、TextFieldの選択状態を解除する(キーボードが下がった状態)。
  4. 再度、対象のTextFieldを選択(タップ)する。
  5. TextField上で全選択がされず、通常の選択状態となる or 選択動作が上手くされない

原因

調べてみたら、以下の同事象と似ている記事を見つけました。

stackoverflowより

これによると、 遅延処理を加えると解消されるとあったので、実際に試してみる

遅延処理について

遅延処理を加える実装方法(以下3つ)とその参考記事をまとめてみました。

色々記事を見た結果、 今回はSwift3以降で使用可能となったdispatch_afterを適用させてみようと思います。

対処

遅延処理dispatch_afterの適用

1.の「TextFieldの選択範囲を指定する方法」に適用する
func textFieldDidBeginEditing(_ textField: UITextField) {

    // 遅延処理 → 0.1秒後に実行
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
    // TextFieldの選択範囲を指定する
    textField.selectedTextRange = textField.textRange(
        from: textField.beginningOfDocument,
        to: textField.endOfDocument)
    }
}
2.の「TextField内の文字列を選択状態にする方法」に適用する
func textFieldDidBeginEditing(_ textField: UITextField) {

    // nilチェック
    if textField != self.urlTextField {
        return
    }
        
 // 遅延処理 → 0.1秒後に実行
 DispatchQueue.main.asyncAfter(deadline: .now()+0.1) {
        // TextField内の文字列を選択状態にする
        textField.selectAll(self.textField.text)
    }
}

修正後、「2回に1度しか全選択の状態にならない」が解消され、 TextField選択時に全選択されるようになった。

参考

[Swift] TextField全選択時の処理で「2回に1度しか全選択の状態にならない」場合の対処方法