我有一个NSTextView
作为它的子类NSTextStorage
委托。 我试图做两件事情:
- 突出显示在某些方面的文本
- 评估文本,然后追加答案TextView的。
我在两种不同的方法,无论是通过调用这样做- (void)textStorageWillProcessEditing:(NSNotification *)notification
委托回调。
我可以做语法高亮就好了,但是当涉及到追加我的答案, 将插入点跳转到该行的结束 ,我真的不知道为什么。 我的评价方法如下所示:
NSString *result = ..;
NSRange lineRange = [[textStorage string] lineRangeForRange:[self selectedRange]];
NSString *line = [[textStorage string] substringWithRange:lineRange];
line = [self appendResult:result toLine:line]; // appends the answer
[textStorage replaceCharactersInRange:lineRange withString:line];
这样做,将追加我的成绩不错,但问题是,如前所述,将插入点跳转到最后。
我试过了:
- 包裹在那些上述调
[textStorage beginEditing]
和-endEditing
。 - 改变文本存储,所以我可以事后重置之前保存的选择范围(即插入点),但没有骰子。
我这样做对吗? 我想这样做至少hackish的方式,而且我也不能确定这是否是理想的地方做我的解析/高亮。 该文档使我相信这一点,但也许这是错误的。
我知道这个问题已经早就回答了,但我有完全一样的问题。 在我NSTextStorage
子我是做了以下内容:
- (void)processEditing {
//Process self.editedRange and apply styles first
[super processEditing];
}
但是,做正确的事情是这样的:
- (void)processEditing {
[super processEditing];
//Process self.editedRange and apply styles after calling superclass method
}
原因将插入点移动
令人惊奇的是,我从来没有发现一个实际的解释为什么这些建议做(或没有)的工作。
挖掘到它,因为将插入点移动的理由是: .editedCharacters
( NSTextStorageEditedCharacters
在ObjC)影响将插入点从位置NSLayoutManager.processEditing(from:editedMask:...)
如果只有.editedAttributes
/ NSTextStorageEditedAttributes
发送,插入点不会被感动。 这是你想要的东西来实现,当你强调:只有改变属性。
为什么要突出影响将插入点
与突出这里的问题是, NSTextStorage
收集所有edited
单个处理运行期间调用和结合范围内,与所述用户编辑的变化开始(例如打字时的插入),则形成的这种联合,并通过报告的所有范围addAttributes(_:range:)
。 这导致在一个单一的NSLayoutManager.processEditing(from:editedMask:...)
调用-与editedMask
两者[.editedCharacters, .editedAttributes]
所以,你想送.editedAttributes
突出显示的范围,但最终形成了工会.editedCharacters
代替。 该联盟将插入点移动waaaaaaaay超越它应该去。
在更改顺序processEditing
调用超的首部作品,因为布局管理器会通知最终编辑。 但是这种方法仍然会打破一些边缘情况,导致无效的布局或轻摇滚动景色,而你输入非常大的段落。
这是挂接到真正NSTextStorageDelegate
,也顺便说一下。
勾成回调后的布局已经完成真正触发加亮,而不是processEditing
将工作稳健基础上的Cocoa框架内在原因,唯一的解决办法是执行从突出textDidChange(_:)
唯一的,布局处理后,即真正已经完成。 订阅NSTextDidChangeNotification
工作一样好。
缺点:你必须触发方案变动凸显通行证基础字符串,因为这些不会调用textDidChange(_:)
回调。
如果你想了解更多有关该问题的根源,我把更多的我的研究,不同的方法和解决方案的细节在更长的博客文章以供参考。 这篇文章仍然是本身就是一个独立的解决方案: http://christiantietze.de/posts/2017/11/syntax-highlight-nstextstorage-insertion-point-change/
这很简单! 我最终打破这个问题分为两个部分。 我还是我的语法高亮显示的结果textStorage
委托回调,但现在我做我的评价和其他地方附加。
我结束了覆盖两个-insertText:
和-deleteBackwards:
我可能还需要做同样的-deleteForwards:
太)。 两个覆盖如下所示:
- (void)insertText:(id)insertString {
[super insertText:insertString];
NSRange selectedRange = [self selectedRange];
[self doEvaluationAndAppendResult];
[self setSelectedRange:selectedRange];
}
我最后不得不将插入点手动在这里重置。 我仍然希望找出为什么这是必要的,但至少这种感觉就像少了黑客攻击。
文章来源: Modifying NSTextStorage causes insertion point to move to the end of the line