NSTextView select 具体行
NSTextView select specific line
我在 Xcode 10,Objective-C,macOS 不是 iOS。
如果给出了行号,是否可以通过编程方式select NSTextView
中的一行?不是通过更改内容的任何属性,只是 select 就像用户通过三次单击那样。
我知道如何按范围获取 selected 文本,但这次我需要以编程方式 select 文本。
我找到了 selectLine:(id)
,但它似乎是一个插入点。
指向正确方向的指针将非常有用,非常感谢。
此处 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 找到行的有效范围,然后将计数索引增加到该范围的末尾(即从下一行开始)。通过一些小的修改,你可以使用它来找到你想要的行的范围select,然后使用NSTextView的setSelectedRange:
到select它。
这里修改为我认为它可能对您试图完成的工作有用的地方:
- (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 开始。如果您传入大于 numberOfLines 的 lineNumberToSelect,它应该只是一个空操作,selection 应该保留在它所在的位置是。
谢谢@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
}
}
我在 Xcode 10,Objective-C,macOS 不是 iOS。
如果给出了行号,是否可以通过编程方式select NSTextView
中的一行?不是通过更改内容的任何属性,只是 select 就像用户通过三次单击那样。
我知道如何按范围获取 selected 文本,但这次我需要以编程方式 select 文本。
我找到了 selectLine:(id)
,但它似乎是一个插入点。
指向正确方向的指针将非常有用,非常感谢。
此处 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 找到行的有效范围,然后将计数索引增加到该范围的末尾(即从下一行开始)。通过一些小的修改,你可以使用它来找到你想要的行的范围select,然后使用NSTextView的setSelectedRange:
到select它。
这里修改为我认为它可能对您试图完成的工作有用的地方:
- (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 开始。如果您传入大于 numberOfLines 的 lineNumberToSelect,它应该只是一个空操作,selection 应该保留在它所在的位置是。
谢谢@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
}
}