【SwiftUI】画面タッチでキーボードを閉じる方法

実行環境

Swift5.6.1
Xcode14.0
macOS12.6

実装

デモ動画

下のように、
TextFieldへ入力中でも
画面の余白をタップすればキーボードが閉じるミニアプリを作成します。

コーディング

今回コーディングしたのは、ContentViewのファイルのみです。
下のように書き換えれば動くと思います。

import SwiftUI

struct ContentView: View {
    @State var outputText = ""

    var body: some View {
        ZStack {

            Color.green
                .opacity(0.5)
                .edgesIgnoringSafeArea(.all)
                .onTapGesture {
                    UIApplication.shared.closeKeyboard()
                }
                .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardDidShowNotification)) { _ in
                    print("キーボードが開いた")
                }.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardDidHideNotification)) { _ in
                   print("キーボードが閉じた")
                }

            TextField("何か入力してください", text: $outputText)


        }

    }
}

extension UIApplication {
    func closeKeyboard() {
        sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}

上記のように、UIApplicationのextentionを生成し、
onTapGestureのモディファイヤで呼び出すことで、
画面タップでキーボードを閉じています。

中核のコードは以下の部分ですね。

extension UIApplication {
    func closeKeyboard() {
        sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}

ついでに記述していた以下のコードは、
キーボードが開いた・閉じたを通知するコードです。

.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardDidShowNotification)) { _ in
    print("キーボードが開いた")
}
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardDidHideNotification)) { _ in
    print("キーボードが閉じた")
}

丁寧に解説

コード全体が意味不明な方もいると思うので、丁寧にコードの解説をします。

まず、以下のコード

extension UIApplication {
    func closeKeyboard() {
        sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}

このコードでは下の3つの知識が必要かなと思います。
・UIAplication
・sendAction
・UIResponder.resignFirstResponder
それぞれ紹介します。

1つ目の、UIAplication。
公式ドキュメントを日本語訳すれば、下の2点のように書かれていました。
・全てのiOSアプリが必ず1つのインスタンスを持つ、アプリの心臓ともいえるインスタンス
・このクラスのAPIを使えば、デバイス固有の振る舞いを管理することができる


とりあえず、
iOSの振る舞いを管理できる、アプリの中核となるインスタンスと言って良さそうです。

参考) 
Every iOS app has exactly one instance of UIApplication (or, very rarely, a subclass of UIApplication).
(中略)
The APIs in this class allow you to manage device-specific behavior.

Apple公式ドキュメント(UIApplication)



次に、sendAction。
公式ドキュメントを日本語訳すれば、
このメソッドはユーザがタッチした UIControl オブジェクトによって呼び出される
と書かれています。

僕なりの理解としては、
ユーザーのアクションを送信するよって感じですかね。

参考) 
Normally, this method is invoked by a UIControl object that the user has touched. The default implementation dispatches the action method to the given target object or, if no target is specified, to the first responder.

Apple公式ドキュメント(send Action(_: to: from: for:))



最後に、UIResponder.resignFirstResponder。
公式ドキュメントを直訳すれば、
このオブジェクトに、そのウィンドウのファーストレスポンダとしての地位を放棄するよう要求されたことを通知する。
と書かれています。

DeepLさんに直訳お願いしてみましたが、
かなり意味不明なので苦戦した様子です。

僕なりに要約すれば、
フォーカスされている状態を外すためのメソッド
で良いと思います。

参考) 
Notifies this object that it has been asked to relinquish its status as first responder in its window.

Apple公式ドキュメント(UIResponder.resignFirstResponder)

次に、
モディファイヤで呼び出している下のコード部分。

.onTapGesture {
     UIApplication.shared.closeKeyboard()
}

onTapGestureはそのまま、タップされたときに呼び出されるモディファイヤです。
詳しく見たい方Apple公式ドキュメント(onTapGesture(count:perform:))をどうぞ。

ここで、先程のUIApplicationを継承したcloseKeyboardを呼び出しています。
これによって、画面をタップすることでキーボードを閉じることが出来ます。

ここまで見えてくれば、
逆に画面タップでキーボードを開いたり、応用もできそうです。

まとめ

ということで、本記事は画面タッチでキーボードを閉じる方法をまとめました。
アドバイスや改善などあれば本記事の最後のコメント欄からお願いします。
最後まで読んでいただきありがとうございました!

作業効率がグッと上がるPC道具

間違いなしのSwift書籍2冊



コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です