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プロパティを削除してください。

また、 target



self



から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行でコードなしで調べました。 好きな方法を使用してください。








All Articles