Objective c 自定义NSTextView中文本更改所需的方法
我有一个自定义的Objective c 自定义NSTextView中文本更改所需的方法,objective-c,range,subclass,editing,nstextview,Objective C,Range,Subclass,Editing,Nstextview,我有一个自定义的NSTextView,我想确保在以编程方式更改文本时发送所有正确的消息和通知。我主要关心撤销/重做注册,但我通常希望以“正确”的方式进行操作。无论如何 我知道的信息是: -shouldChangeTextInRange:replacementString: -didChangeText 如果我正确理解了文档,在对文本视图的textStorage对象进行任何更改之前,需要发送-shouldChangeTextInRange:replacementString:消息,以确保打开新
NSTextView
,我想确保在以编程方式更改文本时发送所有正确的消息和通知。我主要关心撤销/重做注册,但我通常希望以“正确”的方式进行操作。无论如何
我知道的信息是:
-shouldChangeTextInRange:replacementString:
-didChangeText
textStorage
对象进行任何更改之前,需要发送-shouldChangeTextInRange:replacementString:
消息,以确保打开新的撤消组(并通知所有学员开始编辑)。如果返回YES
,则可以对文本进行更改。应用所有更改后,需要发送-didChangeText
消息以关闭撤消组(并再次通知所有观察者)。是这样吗
当修改现有字符(或属性)时,这些说明对我来说很有意义。我正在处理现有的文本范围,因此很容易知道为affectedCharRange
参数发送什么。当我需要插入一些东西时呢
假设我想在当前插入点索引处插入一个随机单词。我是否需要发送-shouldChangeTextInRange:replacementString:
消息?我不是在修改现有字符,而是在现有字符中添加新字符
如果我确实需要发送此消息,那么affectedCharRange
参数的范围是什么?每当我尝试发送待插入文本的新计算范围时,就会出现“范围超出边界”错误,考虑到文本视图的长度尚未更改,这是有意义的。我是否只发送长度为空的插入点范围(例如,未选择任何内容时,self.selectedRange
)
例如:
- (void)insertRandomWord:(id)sender
{
NSAttributedString *randomAttrStr = [self randomAttributedString];
BOOL shouldChangeText = [self shouldChangeTextInRange:shouldThisBeTheSelectedRange // <-- WTF, mate?
replacementString:randomAttrStr.string];
if ( shouldChangeText ) {
[self.textStorage insertAttributedString:randomAttrStr
atIndex:self.selectedRange.location];
// This should always get called, right?
[self didChangeText];
// Is this where I would set the typing attributes?
self.typingAttributes = [randomAttrStr attributesAtIndex:0 effectiveRange:NULL];
}
}
最后,但并非最不重要的一点是,我是否也需要调用NSTextStorage
“编辑”方法?我指的方法是:
-开始编辑:
-endEditing:
NSTextStorage
时调用这些消息,但对于是否也需要发送这些消息,我有点困惑。它并没有真正说明是否使用-fixAttributesInRange:
,但我知道-endEditing
消息会在编辑操作后调用它来进行清理
我为这些混乱的问题道歉。我只是非常疲倦和困惑,苹果的文档一直…缺乏。如有任何提示、指示和/或建议,将不胜感激。谢谢
- (void)changeTextInRange:(NSRange)range replacementString:(NSString *)replacementString usingBlock:(void (^)(void))block
{
BOOL change = [self shouldChangeTextInRange:range replacementString:replacementString];
if ( change ) {
block();
[self didChangeText];
}
}