首页 > 解决方案 > 在 SwiftUI 和 macOS 11 中获取多行 + 可滚动 TextView 中子字符串的 X/Y 位置

问题描述

计划

我已经使用以下实现在我的 Swift 应用程序(macOS 11)中实现了一个 TextView,它通过将 TextView 放入 ScrollViewer 中来使其可滚动:

https://gist.github.com/unnamedd/6e8c3fbc806b8deb60fa65d6b9affab0

现在,我试图在文本的一侧显示注释,最终应该看起来像这样:

注释

我计划通过

  1. 将自定义 AttributedString-key 设置为 TextView 的 NSAttributedString
  2. 在左侧添加第二个 ScrollView,其中包含注释,并同步两个 ScrollView 的滚动位置(即左侧和 TextView 中的)。
  3. 使用相关子字符串计算每个注释的 Y 位置并放置/绘制注释/连接线

问题

我尝试使用textView.firstRect函数(我在所有其他旧的 SO-questions 中找到)评估子字符串的 Y 位置,但是,除非子字符串在其中的位置,否则它似乎不会返回正确的值使用 TextView 的第一行。

    class TextViewExtended: NSTextView {    

func getAllRectangles() {
    for CurRange in self.selectedRanges {
        self.layoutManager!.ensureLayout(for: self.textContainer!) // S. https://stackoverflow.com/a/30752520/2624880
        let CurRangeAsNSRange:NSRange = CurRange as! NSRange
        var actualRange = NSRange(location: 0, length: self.attributedString().length)
        let rect = self.firstRect(forCharacterRange: CurRangeAsNSRange, actualRange: &actualRange)
    }}}

问题

在 SwiftUI 和 macOS 11 中确定 TextView 子字符串坐标的正确方法是什么?或者有没有人有更简单的想法我怎么能做到这一点?

非常感谢您的任何建议!

附言。我省略了 TextView 实现的完整代码,因为它紧跟上面的教程;如果我应该添加其他代码,请告诉我。

标签: swiftuiuitextviewnsattributedstringnstextview

解决方案


尝试使用actualRange. 像这样的东西:

rect = textView.firstRect(forCharacterRange: range, actualRange: &actualRange)
while actualRange.upperBound < rangeToCheck.upperBound {
    rangeToCheck.length = (rangeToCheck.upperBound - actualRange.upperBound)
    rangeToCheck.location = actualRange.upperBound
    rect = textView.firstRect(forCharacterRange: rangeToCheck, actualRange: &actualRange)
}

推荐阅读