I have an NSTextView where I am getting the current position in the text when the textview is clicked. For this, I am using the NSClickGestureRecognizer which calls a selector that grabs the click position from the .location method of the recognizer. It works as expected however the issue I have is that the click doesn't get recognized by the textView so the insertion point cursor doesn't update in the text view. The actual caret position is updated as if I start typing, the text goes where I last clicked even though the insertion point cursor may be somewhere else. The documentation states that by default, the delaysPrimaryMouseButtonEvents is set to true when using the recognizer with states that the default event will only trigger on gesture failure which isn't what I want as I always want the default event to pass through so I set it to false when initializing the recognizer. What happens when I do this is that the default even goes through but the gesture method is never called. If I remove that, it triggers the gesture method but doesn't pass the event through. It's pretty easy to replicate. Just create a new project with an NSTextView, and use the following ViewController code;
class ViewController: NSViewController, NSTextViewDelegate {
@IBOutlet var textView: NSTextView! {
didSet {
let singleClickGesture = NSClickGestureRecognizer(target: self, action: #selector(singleClickGesture(_:)))
singleClickGesture.numberOfClicksRequired = 1 // single
//If delaysPrimaryMouseButtonEvents set to true or omitted, textView never sets insertion point cursor nor clears any selected text
// but singleClickGesture runs every time
//If delaysPrimaryMouseButtonEvents set to false, textView sets insertion point cursor every time
// but singleClickGesture never runs
// I need the singleClickGesture to run then set the insertion point (Cursor Flashing)
singleClickGesture.delaysPrimaryMouseButtonEvents = false
singleClickGesture.delegate = self
textView.addGestureRecognizer(singleClickGesture)
textView.delegate = self
textView.font = NSFont.systemFont(ofSize: CGFloat(16.0))
self.textView.isSelectable = true
}
}
override func viewDidLoad() {
super.viewDidLoad()
textView.string = """
This is a block of text I will insert into the text view.
It will have multiple lines and will be enough text to reproduce the issue.
"""
}
@objc func singleClickGesture(_ recognizer: NSClickGestureRecognizer) {
print("User clicked in textView")
if recognizer.state == .ended {
let caretLocation = recognizer.location(in: textView)
print("Caret location is: \(caretLocation)")
let cursorPosition = textView.characterIndexForInsertion(at: caretLocation)
print("Cursor position is \(cursorPosition)")
}
}
}
extension ViewController: NSGestureRecognizerDelegate {
}
I've been playing around with this for some time and can't get it to work as I need. If anyone has any suggestion, I would love to hear them. Thx