【发布时间】:2021-01-08 09:04:16
【问题描述】:
我正在开发一个 macOS 应用程序。我想编写一个代码,在NSTextView 的点击位置上显示光标。于是我在StackOverFlow中搜索,发现the following code for iOS:
@objc func didTapTextView(recognizer: UITapGestureRecognizer) {
if recognizer.state == .ended {
textView.isEditable = true
textView.becomeFirstResponder()
let location = recognizer.location(in: textView)
if let position = textView.closestPosition(to: location) {
let uiTextRange = textView.textRange(from: position, to: position)
if let start = uiTextRange?.start, let end = uiTextRange?.end {
let loc = textView.offset(from: textView.beginningOfDocument, to: position)
let length = textView.offset(from: start, to: end)
textView.selectedRange = NSMakeRange(loc, length)
}
}
}
}
所以,要将代码从 iOS 转换为 macOS,我可以:
- 将
UITapGestureRecognizer更改为NSClickGestureRecognizer - 将
textView.becomeFirstResponder()更改为textView.window?.makeFirstResponder(textView)
问题是:
我无法将方法 .closestPosition、.textRange 和 .offset 转换为 macOS,因为它们仅在 UIKit 中可用,并且它们返回 UIKit 值,例如 UITextPosition 和 UITextRange。
最小可重现示例
要重现问题,只需创建一个基于文档的 Cocoa 应用程序(macOS),并添加一个 Scrollable TextView,那么代码将是:
import Cocoa
class ViewController: NSViewController, NSGestureRecognizerDelegate {
@IBOutlet var textView: NSTextView!
override func viewDidLoad() {
super.viewDidLoad()
// Set tap gesture
let singleClickGesture = NSClickGestureRecognizer(target: self, action: #selector(singleClickGesture(_:)))
singleClickGesture.numberOfClicksRequired = 1 // single
singleClickGesture.delegate = self
textView.addGestureRecognizer(singleClickGesture)
// create attributed string
let myAttrString = NSMutableAttributedString(string: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.")
// Write it to the Text View
textView.textStorage?.append(myAttrString)
}
@objc func singleClickGesture(_ recognizer: NSClickGestureRecognizer) {
// Show cursor and set it to position on tapping
if recognizer.state == .ended {
textView.isEditable = true
textView.window?.makeFirstResponder(textView)
// Comment the next 9 lines to see the problem.
// TextView is not responding correctly to mouse clicks.
// The next lines fixes the problem for UIKit (iOS),
// but I couldn't make equivalent code for Cocoa (macOS).
let location = recognizer.location(in: textView)
if let position = textView.closestPosition(to: location) {
let uiTextRange = textView.textRange(from: position, to: position)
if let start = uiTextRange?.start, let end = uiTextRange?.end {
let loc = textView.offset(from: textView.beginningOfDocument, to: position)
let length = textView.offset(from: start, to: end)
textView.selectedRange = NSMakeRange(loc, length)
}
}
}
}
}
解决方案?
【问题讨论】:
-
“在 NSTextView 的点击位置显示光标”是什么意思?
-
因为我正在修改 NSClickGestureRecognizer,所以光标不会移动到我在 NSTextView 中点击的位置,它会一直显示在文本视图的末尾
-
我发布了一个最小的可重现示例
-
我的点击识别器中有更多代码(比如确定点击的段落和行),但我没有在上面的示例中编写它,因为它离题了。