はじめに
前回掲載した 【Swift】 TextFieldをタップした時に全選択できるようにする において、
不具合を見つけたため、今回はその対処方法を載せます。
事象
2回に1度しか全選択の状態にならない
1回目にTextFieldをタップした時は全選択ができているが、再度繰り返し同じ動作をすると全選択とならない。
再現
- シュミレータ起動後、対象のTextFieldを選択(タップ)する。
- キーボードが上がり、TextFieldが全選択される。
- 確認後、TextField以外の部分を選択し、TextFieldの選択状態を解除する(キーボードが下がった状態)。
- 再度、対象のTextFieldを選択(タップ)する。
- TextField上で全選択がされず、通常の選択状態となる or 選択動作が上手くされない
原因
原因のコード
1. TextFieldの選択範囲を指定する方法
ViewController.swift
func textFieldDidBeginEditing(_ textField: UITextField) {
// TextFieldの選択範囲を指定する
textField.selectedTextRange = textField.textRange(
from: textField.beginningOfDocument,
to: textField.endOfDocument)
}
2. TextField内の文字列を選択状態にする方法
ViewController.swift
func textFieldDidBeginEditing(_ textField: UITextField) {
// nilチェック
if textField != self.urlTextField {
return
}
// TextField内の文字列を選択状態にする
textField.selectAll(self.textField.text)
}
対処方法
調べてみたら、以下の同事象と似ている記事を見つけました。
stackoverflowより
これによると、
遅延処理を加えると解消されるとあったので、実際に試してみる
遅延処理について
遅延処理を加える実装方法(以下3つ)とその参考記事を簡単にまとめてみました。
-
performSelector: withObject: afterDelay:
-
dispatch_after
-
DispatchQueue.main.asyncAfter(deadline: )
色々記事を見た結果、
今回はSwift3以降で使用可能となったdispatch_after
を適用させてみようと思います。
遅延処理dispatch_after
の適用
1.の「TextFieldの選択範囲を指定する方法」に適用する
ViewController.swift
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内の文字列を選択状態にする方法」に適用する
ViewController.swift
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選択時に全選択されるようになった。