将数据从简单的 NSView 传递到 SwiftUI 视图 [英] Passing data from simple NSView to SwiftUI View

查看:34
本文介绍了将数据从简单的 NSView 传递到 SwiftUI 视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 SwiftUI 制作 macOS 应用.我有一个符合 NSViewRepresentable 的结构,其目的是检测按下的任何键的键码.我想将 event.keyCode 传回 SwiftUI 并将其保存到环境对象中,以便我可以在应用程序的其他地方使用关键代码.
我知道我应该使用 SwiftUI 协调器,但是我可以找到的所有教程和堆栈溢出问题都使用现成的类,例如具有预配置委托的 UIPageControlUISearchBar.我不确定在使用简单的自定义 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 视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆