I have a NSViewRepresentable
that contains an NSScrollView
with a NSTextView
inside.
struct MultilineTextField: NSViewRepresentable {
typealias NSViewType = NSScrollView
private let scrollView = NSScrollView()
private let textView = NSTextView()
@Binding var text: String
@Binding var loc: NSRange
func makeNSView(context: Context) -> NSScrollView {
textView.string = text
textView.delegate = context.coordinator
scrollView.documentView = textView
return scrollView
}
func updateNSView(_ scrollView: NSScrollView, context: Context) {}
func makeCoordinator() -> Coordinator {
return Coordinator(self)
}
class Coordinator: NSObject, NSTextViewDelegate {
let textField: MultilineTextField
init(_ textField: MultilineTextField) {
self.textField = textField
}
func textDidChange(_ notification: Notification) {
textField.text = textField.textView.string
}
func textViewDidChangeSelection(_ notification: Notification) {
DispatchQueue.main.async {
self.textField.loc = self.textField.textView.selectedRange()
}
}
}
}
I'm trying to extract the selectedRange
of the NSTextView
to be displayed in a different view, eg:
Text(String(loc.location))
It works when the selectedRange
is changed with arrow keys and on mouse down and mouse up, but it seems like textViewDidChangeSelection
doesn't get called when in the middle of dragging the mouse over the text. As a result, the displayed loc.location
value doesn't change while dragging until the mouse is lifted up.
As a workaround, I've tried subclassing NSTextView
to override the mouseMoved
method, but it seems like that doesn't get called either for some reason.
Just to verify that selectedRange
actually gets updated on mouse drag, I tried continually updating loc
(this is in the Coordinator
class):
init(_ textField: MultilineTextField) {
self.textField = textField
super.init()
updateSelection()
}
func updateSelection() {
DispatchQueue.main.async {
self.textField.loc = self.textField.textView.selectedRange()
self.updateSelection()
}
}
This code does work, but also uses 100% CPU for no reason.
Is there a way to be notified when selectedRange
changes in the case of mouse dragging?