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?