Реагировать на события нажатия клавиш в SwiftUI - PullRequest
0 голосов
/ 25 апреля 2020

Я хочу реагировать на нажатия клавиш, такие как клавиша esc в macOS / OSX и при использовании внешней клавиатуры на iPad. Как я могу это сделать?

Я думал об использовании @available / #available с onExitCommand SwiftUI, что выглядело очень многообещающе, но, к сожалению, это только для macOS / OSX , Как я могу реагировать на нажатия клавиш в SwiftUI не только для macOS / OSX?

1 Ответ

0 голосов
/ 26 апреля 2020

Благодаря @ Asperi , направившему меня в правильном направлении, я теперь смог заставить это работать.

Решением было использование UIKeyCommand. Вот что я сделал, но вы можете адаптировать его по-разному в зависимости от вашей ситуации.

У меня есть @EnvironmentObject с именем AppState, который помогает мне установить делегата, поэтому ввод с клавиатуры может отличаться в зависимости от текущее представление.

protocol KeyInput {

    func onKeyPress(_ key: String)
}


class KeyInputController<Content: View>: UIHostingController<Content> {

    private let state: AppState

    init(rootView: Content, state: AppState) {
        self.state = state
        super.init(rootView: rootView)
    }
    @objc required dynamic init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


    override func becomeFirstResponder() -> Bool {
        true
    }

    override var keyCommands: [UIKeyCommand]? {
        switch state.current {
        case .usingApp:
            return [
                UIKeyCommand(input: UIKeyCommand.inputEscape, modifierFlags: [], action: #selector(keyPressed(_:)))
            ]

        default:
            return nil
        }
    }

    @objc private func keyPressed(_ sender: UIKeyCommand) {
        guard let key = sender.input else { return }
        state.delegate?.onKeyPress(key)
    }
}

AppState (@EnvironmentObject):

class AppState: ObservableObject {

    var delegate: KeyInput?
    /* ... */
}

И делегат сцены выглядит примерно так:

let stateObject = AppState()
let contentView = ContentView()
    .environmentObject(stateObject)

// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
    let window = UIWindow(windowScene: windowScene)
    window.rootViewController = KeyInputController(rootView: contentView, state: stateObject)

    /* ... */
}

Это делает его действительно легко добавить функциональность в зависимости от нажатых клавиш.

Соответствует KeyInput, например:

struct ContentView: View, KeyInput {

    /* ... */

    var body: some View {
        Text("Hello world!")
            .onAppear {
                self.state.delegate = self
            }
    }

    func onKeyPress(_ key: String) {
        print(key)
        guard key == UIKeyCommand.inputEscape else { return }
        // esc key was pressed
        /* ... */
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...