【问题标题】:NSTextView select specific lineNSTextView 选择特定行
【发布时间】:2019-06-11 19:28:39
【问题描述】:

我使用的是 Xcode 10、Objective-C、macOS 而不是 iOS。

如果给出了行号,是否可以通过编程方式在NSTextView 中选择一行?无需更改内容的任何属性,只需像用户通过三次单击一样选择它。

我知道如何通过范围获取选定文本,但这次我需要以编程方式选择文本。

我找到了selectLine:(id),但它似乎是一个插入点。 指向正确方向的指针将非常好,非常感谢。

【问题讨论】:

    标签: objective-c macos nstextview


    【解决方案1】:

    https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/TextLayout/Tasks/CountLines.html 此处的 Apple 文档应该对您尝试做的事情有用。

    在他们计算换行文本行的示例中,他们使用 NSLayoutManager 方法 lineFragmentRectForGlyphAtIndex:effectiveRange https://developer.apple.com/documentation/appkit/nslayoutmanager/1403140-linefragmentrectforglyphatindex 来查找行的有效范围,然后将计数索引增加到该范围的末尾(即从下一行开始)。通过一些小的修改,你可以使用它找到你想要选择的行的范围,然后使用 NSTextView 的setSelectedRange: 来选择它。

    这里的它被修改为我认为它可能适用于你想要完成的事情:

    - (void)selectLineNumber:(NSUInteger)lineNumberToSelect {
        NSLayoutManager *layoutManager = [self.testTextView layoutManager];
        NSUInteger numberOfLines = 0;
        NSUInteger numberOfGlyphs = [layoutManager numberOfGlyphs];
        NSRange lineRange;
        for (NSUInteger indexOfGlyph = 0; indexOfGlyph < numberOfGlyphs; numberOfLines++) {
            [layoutManager lineFragmentRectForGlyphAtIndex:indexOfGlyph effectiveRange:&lineRange];
            // check if we've found our line number
            if (numberOfLines == lineNumberToSelect) {
                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                    [self.testTextView setSelectedRange:lineRange];
                }];
                break;
            }
            indexOfGlyph = NSMaxRange(lineRange);
        }
    }
    

    然后你可以这样称呼它:

    [self selectLineNumber:3];
    

    请记住,我们从索引 0 开始。如果您传入的 lineNumberToSelect 大于 numberOfLines,则它应该只是一个空操作,并且选择应该保持在原来的位置。

    【讨论】:

      【解决方案2】:

      感谢@R4N!您的回答帮助我弄清楚如何使用 NSTextView 跳转到特定行。我将您的 Obj-C 转换为 Swift 5:

      func selectLineNumber(lineNumberToJumpTo: Int) {
          let layoutManager = textView.layoutManager!
          var numberOfLines = 1
          let numberOfGlyphs = layoutManager.numberOfGlyphs
          var lineRange: NSRange = NSRange()
          var indexOfGlyph = 0
          
          while indexOfGlyph < numberOfGlyphs {
            layoutManager.lineFragmentRect(forGlyphAt: indexOfGlyph, effectiveRange: &lineRange, withoutAdditionalLayout: false)
            // check if we've found our line number
            if numberOfLines == lineNumberToJumpTo {
              
              textView.selectedRange = lineRange
              textView.scrollRangeToVisible(lineRange)
              
              break
            }
            indexOfGlyph = NSMaxRange(lineRange)
            numberOfLines += 1
          }
        }
      

      【讨论】:

        猜你喜欢
        • 2014-03-27
        • 1970-01-01
        • 1970-01-01
        • 2022-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-28
        • 1970-01-01
        相关资源
        最近更新 更多