我正在使用SwiftUI制作macOS应用程序。我有一个符合NSViewRepresentable
的结构,其目的是检测所按下的键的键代码。我想将event.keyCode
传递回SwiftUI并将其保存到环境对象中,以便可以在应用程序的其他位置使用键代码。
我知道我应该使用SwiftUI协调器,但是我可以找到的所有教程和堆栈溢出问题都使用具有预先配置的委托的现成类,例如UIPageControl
或UISearchBar
。我不确定使用简单的自定义NSView
时该怎么做。有人可以解释使用自定义NSViewRepresentable
时如何将数据从@EnvironmentObject
结构传递到我的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控制台,因此检测正常。
答案 0 :(得分:4)
这是一个解决方案(包含一些重复的部分)。经过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 !!!
}
}
}