LoginSignup
5

More than 1 year has passed since last update.

UITableView上で、キーボードを閉じる処理

Last updated at Posted at 2020-10-24

はじめに

TableViewのセルにTextFieldTextViewを配置した際に、これら以外の部分をタップした時のキーボードを閉じる処理に少し手こずりましたので、備忘録として投稿します。

動作環境

【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で準備してある下記関数でタッチイベントを取得し、キーボードを閉じようと試みましたが、処理が呼ばれませんでした。調べるとUIScrollViewUITableViewはデフォルトではタッチイベントを取得できないようになっているらしいです。

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

個人的な意見にはなりますが、オリジナルアプリの登録画面の実装の際にこの問題に直面しましたが、キーボードが表示されている間はフォーカスがあたっているTextViewTextField以外は触れなくしててもいいかなと考えています。

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
5