替换文本后防止 NSTextView 自动滚动到顶部

Prevent NSTextView auto scroll to top after replace text

我正在努力解决这个看似简单的问题,但还没有找到好的解决方案:

我在NSScrollView里面有一个NSTextView,textView是不可编辑的,整个textView的stringValue每2s被替换一次

当 textView 高度小于 scrollView 高度时,它工作正常,但当它更长时,scrollView 总是会在每次文本替换后自动滚动回顶部。我希望它在更新后保持相同的偏移量。

我现在的工具,可以用,但是由于手动滚动导致闪烁,希望找到一种方法可以保持偏移量不闪烁,不知道有没有配置可以做到:

CGFloat offset = self.scrollView.documentVisibleRect.origin.y;
self.newText = .....; // Update the textView string via binding
if (offset > 0) {
      CGFloat maxHeight = fabs(self.scrollView.documentView.frame.size.height - self.scrollView.frame.size.height) + 2;
      dispatch_async(dispatch_get_main_queue(), ^{
            [self.scrollView.documentView scrollPoint:CGPointMake(0, MIN(offset, maxHeight))];
      });
}

在检查了一些类似的 iOS 问题后,我找到了一种方法,重点不是使用绑定替换文本或通过 textView.string:

进行设置
NSRange selectedRange = self.textView.selectedRange;
[self.textView.textStorage beginEditing];
NSRange rangeToReplace = NSMakeRange(0, self.textView.textStorage.string.length);
[self.textView.textStorage replaceCharactersInRange:rangeToReplace withString:newText];
[self.textView.textStorage endEditing];

// This is to keep the selected text
if(selectedRange.location != NSNotFound && NSMaxRange(selectedRange) <= rangeToReplace.length) {
   [self.textView setSelectedRange:NSMakeRange(selectedRange.location, selectedRange.length)];
}