问题描述
我正在使用 SwiftUI 制作 macOS 应用.我有一个符合 NSViewRepresentable
的结构,其目的是检测按下的任何键的键码.我想将 event.keyCode
传回 SwiftUI 并将其保存到环境对象中,以便我可以在应用程序的其他地方使用关键代码.
我知道我应该使用 SwiftUI 协调器,但是我可以找到的所有教程和堆栈溢出问题都使用现成的类,例如具有预配置委托的 UIPageControl
或 UISearchBar
.我不确定在使用简单的自定义 NSView
时该怎么做.有人能解释一下在使用自定义 NSView
时如何将数据从 NSViewRepresentable
结构传递到我的 @EnvironmentObject
中吗?
I'm making a macOS app with SwiftUI. I have a struct conforming to NSViewRepresentable
, whose purpose is to detect the key code of whichever key was pressed. I want to pass the event.keyCode
back to SwiftUI and save it into an environment object so I can use the key code elsewhere in my app.
I know I am supposed to use SwiftUI coordinators, but all tutorials and Stack Overflow questions I can find use ready-made classes such as UIPageControl
or UISearchBar
that have pre-configured delegates. I'm not sure what to do when using a simple custom NSView
. Can somebody explain how to pass the data from the NSViewRepresentable
struct into my @EnvironmentObject
when using a custom NSView
?
struct KeyboardEvent: NSViewRepresentable {
class KeyView: NSView {
override var acceptsFirstResponder: Bool { true }
override func keyDown(with event: NSEvent) {
print("\(event.keyCode)")
}
}
func makeNSView(context: Context) -> NSView {
let view = KeyView()
DispatchQueue.main.async {
view.window?.makeFirstResponder(view)
}
return view
}
func updateNSView(_ nsView: NSView, context: Context) {
}
}
struct ContentView: View {
@EnvironmentObject var input: KeyboardInput // save the keyCode here
var body: some View {
VStack {
Text(input.keyCode)
KeyboardEvent()
}
}
}
现在它正常地将关键代码打印到 Xcode 控制台,因此检测工作正常.
Right now it prints the key code normally to the Xcode console, so the detection works fine.
推荐答案
这是一个解决方案(包含一些复制的部分).使用 Xcode 11.4/macOS 10.15.4 测试
Here is a solution (with some replicated parts). Tested with Xcode 11.4 / macOS 10.15.4
class KeyboardInput: ObservableObject {
@Published var keyCode: UInt16 = 0
}
struct KeyboardEvent: NSViewRepresentable {
@Binding var keyStorage: UInt16 // << here !!
init(into storage: Binding<UInt16>) {
_keyStorage = storage
}
class KeyView: NSView {
var owner: KeyboardEvent? // << view holder
override var acceptsFirstResponder: Bool { true }
override func keyDown(with event: NSEvent) {
print("\(event.keyCode)")
owner?.keyStorage = event.keyCode
}
}
func makeNSView(context: Context) -> NSView {
let view = KeyView()
view.owner = self // << inject
DispatchQueue.main.async {
view.window?.makeFirstResponder(view)
}
return view
}
func updateNSView(_ nsView: NSView, context: Context) {
}
}
struct ContentView: View {
@EnvironmentObject var input: KeyboardInput // save the keyCode here
var body: some View {
VStack {
Text("Code: \(input.keyCode)")
KeyboardEvent(into: $input.keyCode) // << binding !!!
}
}
}
这篇关于将数据从简单的 NSView 传递到 SwiftUI 视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!