如何在NSTextview中实现撤销功能

8

我希望在替换NSTextView中的一部分文本后实现撤销操作。我使用以下代码替换文本的一部分:

- (void)omeAction
{
    NSString *fullString = [self.textView string];
    NSRange selectedRange = [self.textView selectedRange];
    NSString *selectedString = [fullString substringWithRange:selectedRange];

    NSString *stringToReplace = ...;
    [[self.textView textStorage] beginEditing];
    [[self.textView  textStorage] replaceCharactersInRange:selectedRange withString:stringToReplace];
    [[self.textView textStorage] endEditing];
}

撤销操作时,我无法真正撤销文本替换。

2个回答

10

根据Cocoa文本体系结构指南:文本编辑-文本更改通知和代理消息

实际上进行文本更改时,必须确保不同部分的文本系统正确执行和记录更改。您可以通过使用shouldChangeTextInRange:replacementString:和didChangeText消息来对每个潜在更改的批次加以标记。这些方法确保发送适当的代理消息并发布通知。…

从我的经验来看,这包括生成相关的撤消操作。

因此,您应该执行以下操作:

if ([self.textView shouldChangeTextInRange:selectedRange replacementString:stringToReplace])
{
    [[self.textView textStorage] beginEditing];
    [[self.textView textStorage] replaceCharactersInRange:selectedRange withString:stringToReplace];
    [[self.textView textStorage] endEditing];
    [self.textView didChangeText];
}

抱歉,我没有完整阅读问题。我以为这是关于撤销的一般性问题(标题不够明确)。在我的情况下,撤销根本无法工作,最终发现是因为nstextview没有注册某些关键事件。请忽略前文。 - Charlton Provatas
谢谢,shouldChangeTextInRange 帮助正确启动了撤销功能。 - Marek H

2

首先,我尝试解决撤销问题,使用shouldChangeTextInRange:replacementString:方法可以解决。但是我发现insertText:replacementRange:方法也能达到同样的效果。

[self insertText:attributedString replacementRange:range];

或者:

if ([textView shouldChangeTextInRange:range replacementString:string]) { //string
  [textStorage beginEditing];
  [textStorage replaceCharactersInRange:range withAttributedString:attributedString];
  [textStorage endEditing];
  [textView didChangeText];
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接