【问题标题】:SwiftUI iOS - how to capture hardware key eventsSwiftUI iOS - 如何捕获硬件按键事件
【发布时间】:2020-05-04 22:47:03
【问题描述】:

我是 iOS 开发新手。按照教程,我使用 SwiftUI 创建了一个简单的计算器。

我的 iPad 上连接了一个键盘,我希望能够使用键盘输入值。

如何在 SwiftUI 应用程序(没有文本字段)中捕获和处理硬件键盘事件? 我尝试在 SceneDelegate (UIResponder) 上使用 keyCommands,如此处所示,但这对我不起作用。只要我按下 iPad 上的任何键,我就会在 XCode 跟踪视图中看到“与守护程序的连接已失效”。

 class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    override var canBecomeFirstResponder: Bool {
        return true;
    }
    override var keyCommands: [UIKeyCommand]? {
        return [
            UIKeyCommand(input: "a", modifierFlags: [], action: #selector(test)),
            UIKeyCommand(input: UIKeyCommand.inputLeftArrow, modifierFlags: [], action: #selector(test))
        ]
    }

    @objc func test(_ sender: UIKeyCommand) {
        print("test was pressed")
    }

谢谢

【问题讨论】:

    标签: swiftui uikeycommand


    【解决方案1】:

    它需要覆盖托管视图控制器,并且一切正常。使用 Xcode 11.2 / iOS 13.2 测试

    这是示例代码

    class KeyTestController<Content>: UIHostingController<Content> where Content: View {
    
        override func becomeFirstResponder() -> Bool {
            true
        }
    
        override var keyCommands: [UIKeyCommand]? {
            return [
                UIKeyCommand(input: "1", modifierFlags: [], action: #selector(test)),
                UIKeyCommand(input: "0", modifierFlags: [], action: #selector(test)),
                UIKeyCommand(input: UIKeyCommand.inputLeftArrow, modifierFlags: [], action: #selector(test))
            ]
        }
    
        @objc func test(_ sender: UIKeyCommand) {
            print(">>> test was pressed")
        }
    
    }
    

    在下面的SceneDelegate 某处

    window.rootViewController = KeyTestController(rootView: contentView)
    

    【讨论】:

      【解决方案2】:

      如果您使用的是 SwiftUI 生命周期,@Asperi 还会在这篇文章中展示如何访问 rootViewController - Hosting Controller When Using iOS 14 @main

      总之,HostingWindowFinder 追踪rootViewController 的可变版本并提供对它的访问。

      struct ContentView: View {
      
          var body: some View {
            Text("Demo Root Controller access")
              .withHostingWindow { window in
                  window?.rootViewController = KeyController(rootView: ContentView())
              }
          }
      }
      
      extension View {
          func withHostingWindow(_ callback: @escaping (UIWindow?) -> Void) -> some View {
              self.background(HostingWindowFinder(callback: callback))
          }
      }
      
      struct HostingWindowFinder: UIViewRepresentable {
          var callback: (UIWindow?) -> ()
      
          func makeUIView(context: Context) -> UIView {
              let view = UIView()
              DispatchQueue.main.async { [weak view] in
                  self.callback(view?.window)
              }
              return view
          }
      
          func updateUIView(_ uiView: UIView, context: Context) {
          }
      }
      

      还有

      如果您只想监控原始键盘输入,请使用 pressesBegan(...) - WWDC 2019 Talk

      class KeyController<Content>: UIHostingController<Content> where Content: View {
      
          override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
              for press in presses {
                  guard let key = press.key else { continue }
                  print(key)
              }
          }
      }
      

      非常感谢@Asperi! ❤️

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-31
        • 2011-09-19
        相关资源
        最近更新 更多