はじめに
TableView
のセルにTextField
やTextView
を配置した際に、これら以外の部分をタップした時のキーボードを閉じる処理に少し手こずりましたので、備忘録として投稿します。
動作環境
【Xcode】Version 12.0.1
【Swift】Version 5.3
実装コード
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
// タップ認識するためのインスタンスを生成
let tapGesture = UITapGestureRecognizer(
target: self,
action: #selector(dismissKeyboard))
tapGesture.cancelsTouchesInView = false
// Viewに追加
view.addGestureRecognizer(tapGesture)
}
// キーボードと閉じる際の処理
@objc public func dismissKeyboard() {
view.endEditing(true)
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath)
return cell
}
}
class TableViewCell: UITableViewCell {
@IBOutlet weak var textField: UITextField!
override func awakeFromNib() {
super.awakeFromNib()
textField.delegate = self
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
extension TableViewCell: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
実装詳細
はじめに、Swiftで準備してある下記関数でタッチイベントを取得し、キーボードを閉じようと試みましたが、処理が呼ばれませんでした。調べるとUIScrollView
やUITableView
はデフォルトではタッチイベントを取得できないようになっているらしいです。
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
上記の方法がダメだったので解決策として、UITapGestureRecognizer
を使ってタップを認識できるようにし。キーボードを閉じるようにしました。
// タップ認識するためのインスタンスを生成
let tapGesture = UITapGestureRecognizer(
target: self,
action: #selector(dismissKeyboard))
view.addGestureRecognizer(tapGesture)
// キーボードと閉じる際の処理
@objc public func dismissKeyboard() {
view.endEditing(true)
}
UITapGestureRecognizer
を設定すると他ViewへのTapを認識しなくなります。理由としましては、cancelsTouchesInView
がデフォルトでtrue
になっているからだそうで、下記コードを追加することで解消されます。
tapGesture.cancelsTouchesInView = false
個人的な意見にはなりますが、オリジナルアプリの登録画面の実装の際にこの問題に直面しましたが、キーボードが表示されている間はフォーカスがあたっているTextView
やTextField
以外は触れなくしててもいいかなと考えています。