处理通过 NSViewRepresentable 嵌入的 NSTextView 中的键盘输入? (SwiftUI/MacOS)
Handle keyboard inputs in NSTextView embedded via NSViewRepresentable? (SwiftUI/MacOS)
我是 Swift 的新手UI,我很困惑。我设法将 NSTextView 嵌入到我的 SwiftUI 视图中,并使用以下代码绑定它的文本。
我不明白的;有没有办法处理键盘输入 到 NSTextView 并相应地更改其文本(例如 CMD + R 将所选文本的文本颜色设置为红色)?甚至有什么方法可以与 SwiftUI 中的 UI-Elements 交互吗?
"RichTextField"
struct RichTextField: NSViewRepresentable {
typealias NSViewType = NSTextView
@Binding var attributedString: NSAttributedString
func makeNSView(context: Context) -> NSTextView {...
// [...]
}
查看
struct EditWindow: View {
@ObservedObject var model: EditEntryViewModel
@Binding var isPresented: Bool
var body: some View {
RichTextField(attributedString: self.$model.answer1, isEditable: true)
// [...]
}
}
此外,我已经设法在 AppDelegate 中设置了一个菜单命令,但是我如何使用它来更改任意视图的 NSTextView 中的文本(在特定位置)?
@IBAction func setTagImportant(_ sender: Any) {
print("setTagImportant")
}
非常感谢你为我阐明了这一点...
具有讽刺意味的是,在最终发布这个问题后,我立即找到了解决方案;只需将 NSTextView 子类化,然后重写 keyDown:
import SwiftUI
class RichTextFieldExtended: NSTextView {
override func keyDown(with event: NSEvent) {
if event.modifierFlags.contains(NSEvent.ModifierFlags.command) {
switch event.keyCode {
case 18: // 1
print("1 PRESSED")
default:
print("keyCode \(event.keyCode) wasn't handled")
super.keyDown(with: event)
}
} else {
super.keyDown(with: event)
}
}
}
然后在NSViewRepresentable中包含子类化的NSTextView,如下
struct RichTextField: NSViewRepresentable {
typealias NSViewType = RichTextFieldExtended
@Binding var attributedString: NSAttributedString
var isEditable: Bool
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeNSView(context: Context) -> RichTextFieldExtended {
let textView = RichTextFieldExtended(frame: .zero)
textView.textStorage?.setAttributedString(self.attributedString)
textView.isEditable = isEditable
textView.delegate = context.coordinator
textView.translatesAutoresizingMaskIntoConstraints = false
textView.autoresizingMask = [.width, .height]
return textView
}
func updateNSView(_ nsView: RichTextFieldExtended, context: Context) {
// nsView.textStorage!.setAttributedString(self.attributedString)
}
// Source: https://medium.com/fantageek/use-xib-de9d8a295757
class Coordinator: NSObject, NSTextViewDelegate {
let parent: RichTextField
init(_ RichTextField: RichTextField) {
self.parent = RichTextField
}
func textDidChange(_ notification: Notification) {
guard let textView = notification.object as? RichTextFieldExtended else { return }
self.parent.attributedString = textView.attributedString()
}
}
}
干杯
我是 Swift 的新手UI,我很困惑。我设法将 NSTextView 嵌入到我的 SwiftUI 视图中,并使用以下代码绑定它的文本。
我不明白的;有没有办法处理键盘输入 到 NSTextView 并相应地更改其文本(例如 CMD + R 将所选文本的文本颜色设置为红色)?甚至有什么方法可以与 SwiftUI 中的 UI-Elements 交互吗?
"RichTextField"
struct RichTextField: NSViewRepresentable {
typealias NSViewType = NSTextView
@Binding var attributedString: NSAttributedString
func makeNSView(context: Context) -> NSTextView {...
// [...]
}
查看
struct EditWindow: View {
@ObservedObject var model: EditEntryViewModel
@Binding var isPresented: Bool
var body: some View {
RichTextField(attributedString: self.$model.answer1, isEditable: true)
// [...]
}
}
此外,我已经设法在 AppDelegate 中设置了一个菜单命令,但是我如何使用它来更改任意视图的 NSTextView 中的文本(在特定位置)?
@IBAction func setTagImportant(_ sender: Any) {
print("setTagImportant")
}
非常感谢你为我阐明了这一点...
具有讽刺意味的是,在最终发布这个问题后,我立即找到了解决方案;只需将 NSTextView 子类化,然后重写 keyDown:
import SwiftUI
class RichTextFieldExtended: NSTextView {
override func keyDown(with event: NSEvent) {
if event.modifierFlags.contains(NSEvent.ModifierFlags.command) {
switch event.keyCode {
case 18: // 1
print("1 PRESSED")
default:
print("keyCode \(event.keyCode) wasn't handled")
super.keyDown(with: event)
}
} else {
super.keyDown(with: event)
}
}
}
然后在NSViewRepresentable中包含子类化的NSTextView,如下
struct RichTextField: NSViewRepresentable {
typealias NSViewType = RichTextFieldExtended
@Binding var attributedString: NSAttributedString
var isEditable: Bool
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeNSView(context: Context) -> RichTextFieldExtended {
let textView = RichTextFieldExtended(frame: .zero)
textView.textStorage?.setAttributedString(self.attributedString)
textView.isEditable = isEditable
textView.delegate = context.coordinator
textView.translatesAutoresizingMaskIntoConstraints = false
textView.autoresizingMask = [.width, .height]
return textView
}
func updateNSView(_ nsView: RichTextFieldExtended, context: Context) {
// nsView.textStorage!.setAttributedString(self.attributedString)
}
// Source: https://medium.com/fantageek/use-xib-de9d8a295757
class Coordinator: NSObject, NSTextViewDelegate {
let parent: RichTextField
init(_ RichTextField: RichTextField) {
self.parent = RichTextField
}
func textDidChange(_ notification: Notification) {
guard let textView = notification.object as? RichTextFieldExtended else { return }
self.parent.attributedString = textView.attributedString()
}
}
}
干杯