iOSでキーボードを非表示にするタップジェスチャー(Swift 3)

この記事では、基本から実装までのビューをクリックして、キーボードを非表示にする方法を1行で、またはコードなしで分析します。




基本


次のケースは非常に一般的です。背景をクリックして、キーボードを非表示にします。


基本的な解決策は、 UITextFieldへのリンクを作成し、テキストフィールドから選択を削除するメソッドでUITapGestureRecognizerを作成し、次のようにすることです。


この記事ではSwift 3を使用していますが、他のバージョンやObjective-Cでも実装できます

 class ViewController: UIViewController { @IBOutlet weak var textField: UITextField! override func viewDidLoad() { super.viewDidLoad() let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapGesture)) view.addGestureRecognizer(tapGesture) } func tapGesture() { textField.resignFirstResponder() } } 

このコードの問題:



読みやすくする


最初の問題を解決するには、別の関数でジェスチャーを作成および追加するためのコードを取り出します。


 class ViewController: UIViewController { @IBOutlet weak var textField: UITextField! override func viewDidLoad() { super.viewDidLoad() addTapGestureToHideKeyboard() } func addTapGestureToHideKeyboard() { let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapGesture)) view.addGestureRecognizer(tapGesture) } func tapGesture() { textField.resignFirstResponder() } } 

コードはさらに多くなりましたが、よりクリーンで、論理的で、見た目も快適になりました。


コード削減


2番目の問題を解決するために、 UIViewは次のメソッドがあります。


 func endEditing(_ force: Bool) -> Bool 

彼は、ビュー自体またはそのサブビューから選択を削除するだけです。 彼のおかげで、コードを大幅に簡素化できます。


 class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() addTapGestureToHideKeyboard() } func addTapGestureToHideKeyboard() { let tapGesture = UITapGestureRecognizer(target: view, action: #selector(view.endEditing)) view.addGestureRecognizer(tapGesture) } } 

手順に従う場合は、必ずIBからtextFieldプロパティを削除してください。
また、 targetselfからview変更しview

コードは目を楽しませ始めました! ただし、これを各コントローラーにコピーする必要があります。


コピーソリューション


再利用のために、 extensionコントローラーを追加する方法を紹介します。


 extension UIViewController { func addTapGestureToHideKeyboard() { let tapGesture = UITapGestureRecognizer(target: view, action: #selector(view.endEditing)) view.addGestureRecognizer(tapGesture) } } 

そして、コントローラーのコードは次のようになります。


 class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() addTapGestureToHideKeyboard() } } 

きれいな1行のコードで、再利用可能です! パーフェクト!


マルチビュー


上記のソリューションは非常に優れていますが、欠点が1つあります。特定のビューにジェスチャーを追加することはできません。


このケースを解決するには、 UIView拡張機能を使用します。


 extension UIView { func addTapGestureToHideKeyboard() { let tapGesture = UITapGestureRecognizer(target: self, action: #selector(endEditing)) addGestureRecognizer(tapGesture) } } 

したがって、コントローラーコードは次のようになります。


 class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.addTapGestureToHideKeyboard() } } 

ここで別の問題が発生します。この拡張機能は、コントローラービューの問題のみを解決します。 someViewをビューに追加し、その上にジェスチャーを配置すると、機能しなくなります。 これは、 endEditingメソッドがアクティブビューを含むビューまたはそれ自体のビューに対してのみ機能し、テキストフィールドがその中にない可能性が高いためです。 この問題を解決します。


なぜなら コントローラーのビューには必ずアクティブビューが含まれ、追加したビューは常にその階層内にあります。その後、 superviewを介してsuperviewコントローラーに到達し、そのendEditingを呼び出します。


UIView拡張機能を通じてコン​​トローラーのビューを取得します。


 var topSuperview: UIView? { var view = superview while view?.superview != nil { view = view!.superview } return view } 

セレクタを次のように変更して、すぐに言います


 #selector(topSuperview?.endEditing) 

それでも動作しません。 上記の構成を呼び出すメソッドを追加する必要があります。


 func dismissKeyboard() { topSuperview?.endEditing(true) } 

次に、セレクターを次のように置き換えます。


 #selector(dismissKeyboard) 

したがって、UIViewの拡張機能は次のようになります。


 extension UIView { func addTapGestureToHideKeyboard() { let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) addGestureRecognizer(tapGesture) } var topSuperview: UIView? { var view = superview while view?.superview != nil { view = view!.superview } return view } func dismissKeyboard() { topSuperview?.endEditing(true) } } 

次に、任意のビューにaddTapGestureToHideKeyboard()を使用して、キーボードを非表示にします。


KeyboardHideManager


アイコン


上記のソリューションを長い間使用していましたが、1行でもビューインストール機能を汚染していることに気付き始めました。 また、(まれですが、それでも起こります) viewDidLoad唯一のメソッドである場合、あまり美しくありません:


 override func viewDidLoad() { super.viewDidLoad() addTapGestureToHideKeyboard() } 

スペースと合わせて5行かかるため、コントローラーの純度に大きく影響します! コードなしでこれをすべて実行することを考えていたので、コントローラーに1行余分に追加する必要はありません。 Objectを使用してIBに追加できるクラスを作成しました


対象


そして、 @IBOutlet必要な@IBOutletをバインドし@IBOutlet


プレビュー


このクラスの実装は最も簡単です-上記で作成した関数を使用して、各ビューにジェスチャーを追加します。


 final public class KeyboardHideManager: NSObject { @IBOutlet internal var targets: [UIView]! { didSet { for target in targets { addGesture(to: target) } } } internal func addGesture(to target: UIView) { let gesture = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) target.addGestureRecognizer(gesture) } @objc internal func dismissKeyboard() { targets.first?.topSuperview?.endEditing(true) } } extension UIView { internal var topSuperview: UIView? { var view = superview while view?.superview != nil { view = view!.superview } return view } } 

このクラスを使用するには、3つの簡単な手順が必要です。



usage_1



usage_2



usage_3


はい、このコントローラーにはこの行がないため、単一行(または定義されたビューが複数ある場合は複数行)を書き込むよりも多くのアクションがあります。


誰かがコードに線を書く方が良いと言うかもしれません、それはより明確で、一方で彼らは正しいでしょう。 コントローラーから可能な限りすべてを削除して、それを促進することに賛成です。


このクラスをCocoaPods経由で接続するか、単にプロジェクトにコピーできます。


ライブラリ自体とその接続に関する完全なReadMeを使用して、 KeyboardHideManagerのソースコードにリンクします。


まとめ


人気のあるケースの実装を分解し、そのソリューションのいくつかを1行でコードなしで調べました。 好きな方法を使用してください。



Source: https://habr.com/ru/post/J318434/


All Articles