在我正在处理的应用程序中,用户输入纯文本,应用程序通过将文本转换为NSAttributedString来重新格式化文本,并显示它。这一切都在现场发生。
目前,我在NSTextView的textDidChange委托方法上执行以下操作:
- (void)textDidChange:(NSNotification *)notification {
// saving the cursor position
NSInteger insertionPoint = [[[self.mainTextView selectedRanges] objectAtIndex:0] rangeValue].location;
// this grabs the text view's contact as plain text
[self updateContentFromTextView];
// this creates an attributed strings and displays it
[self updateTextViewFromContent];
// resetting the cursor position
self.mainTextView.selectedRange = NSMakeRange(insertionPoint, 0);
}
虽然这种方法很有效,但并不理想。文本似乎瞬间闪烁(你特别注意拼写错误下的红点),当光标先前接近可见矩形的一个边缘时,滚动位置会重置。就我而言,这是一个非常不良的副作用。
所以我的问题是:有没有更好的方法来做我想做的事情?
答案 0 :(得分:5)
我认为你对NSTextView
如何运作有一点误解。用户永远不会输入“普通字符串”,NSTextView
的数据存储总是一个NSTextStorage
对象,它是NSMutableAttributedString
的子类。
您需要做的是为用户正在编辑的现有属性字符串添加/删除属性,而不是替换整个字符串。
您也不应对‑textDidChange:
委托方法中的字符串进行更改,因为从该方法更改字符串可能会导致另一个更改通知。
相反,您应该实现委托方法‑textStorageDidProcessEditing:
。每当文本更改时都会调用此方法。然后,您可以像这样修改字符串:
- (void)textStorageDidProcessEditing:(NSNotification*)notification
{
//get the text storage object from the notification
NSTextStorage* textStorage = [notification object];
//get the range of the entire run of text
NSRange aRange = NSMakeRange(0, [textStorage length]);
//for example purposes, change all the text to yellow
//remove existing coloring
[textStorage removeAttribute:NSForegroundColorAttributeName range:aRange];
//add new coloring
[textStorage addAttribute:NSForegroundColorAttributeName
value:[NSColor yellowColor]
range:aRange];
}