【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をタップした時は全選択ができているが、再度繰り返し同じ動作をすると全選択とならない。
再現
- シュミレータ起動後、対象のTextFieldを選択(タップ)する。
- キーボードが上がり、TextFieldが全選択される。
- 確認後、TextField以外の部分を選択し、TextFieldの選択状態を解除する(キーボードが下がった状態)。
- 再度、対象のTextFieldを選択(タップ)する。
- TextField上で全選択がされず、通常の選択状態となる or 選択動作が上手くされない
原因
調べてみたら、以下の同事象と似ている記事を見つけました。
stackoverflowより
これによると、 遅延処理を加えると解消されるとあったので、実際に試してみる
遅延処理について
遅延処理を加える実装方法(以下3つ)とその参考記事をまとめてみました。
performSelector: withObject: afterDelay:
dispatch_after
DispatchQueue.main.asyncAfter(deadline: )
色々記事を見た結果、
今回は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選択時に全選択されるようになった。