LoginSignup
2
1

More than 1 year has passed since last update.

【SwiftUI】Combineでキーボードを監視する

Last updated at Posted at 2022-12-12

はじめに

私は現在カスタムキーボードを作成していて、キーボードの状態を知る方法を色々試しています。
この方法はCustomKeyboardExtensionでは使用できませんでしたが、メインターゲットでは使用できました。
せっかく試したので記事にしておきます。

サンプルアプリ

ちょっと見にくいですが、以下の2項目を表示しています。

  • キーボード状態(開いている or 閉じている)
  • キーボードサイズ(width, height)
    RPReplay_Final1670849788_MP4_AdobeExpress.gif

実装

View

ContentView
import SwiftUI

struct ContentView: View {
    @StateObject private var viewModel = ViewModel()
    var body: some View {
        NavigationStack {
            List {
                TextField("タップしてください", text: $viewModel.text)

                LabeledContent {
                    Text(viewModel.keyboardStatus.rowValue)
                } label: {
                    Text("状態")
                }

                LabeledContent {
                    Text(viewModel.keyboardRect.size.debugDescription)
                } label: {
                    Text("サイズ")
                }
                Button {
                    viewModel.closeKeyboard()
                } label: {
                    Text("キーボードを閉じる")
                }
            }
            .navigationTitle("キーボード監視")
        }
    }
}

ViewModel

ViewModel
import Combine
import UIKit

final class ViewModel: ObservableObject {
    @Published var text: String = ""

    @Published var keyboardStatus: KeyboardStatus = .hide

    @Published var keyboardRect: CGRect = .zero

    private let notificationCenter = NotificationCenter.default

    private var cancellable = Set<AnyCancellable>()

    init() {
        notificationCenter.publisher(for: UIResponder.keyboardDidChangeFrameNotification)
            .sink { [weak self] notification in
                guard
                    let self,
                    let userInfo = notification.userInfo,
                    let rect = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect
                else { return }

                self.keyboardRect = rect

                if rect == .zero {
                    self.keyboardStatus = .hide
                } else {
                    self.keyboardStatus = .show
                }
            }
            .store(in: &cancellable)
    }

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

Model

KeyboardStatus
import Foundation

enum KeyboardStatus {
    case show
    case hide

    var rowValue: String {
        switch self {
        case .show:
            return "開いている"
        case .hide:
            return "閉じている"
        }
    }
}

おわり

2
1
0

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
  3. You can use dark theme
What you can do with signing up
2
1