我创建了一个带有 NSTextView 和按钮的简单演示应用程序,为 textView 提供了 NSTextViewDelegate 并添加了一个操作:
- (IBAction)actionButtonClicked:(id)sender {
NSString *oldText = [[[self.textView textStorage] string] copy];
NSString *newText = @"And... ACTION!";
[[self.textView undoManager] registerUndoWithTarget:self.textView
selector:@selector(setString:)
object:oldText];
[[self.textView undoManager] setActionName:@"ACTION"];
[self.textView setString:newText];
}
如果我手动更改文本,撤消/重做工作不会出现问题。但是,如果我使用操作方法更改文本,撤消将按预期工作,但重做不再起作用(什么也没有发生)并且撤消管理器似乎被打乱......
好的 - 为了避免 NSTextView 出现问题,我创建了一个模型类,将 NSTextView 绑定到它并将撤消/重做移动到模型,但这显示了与以前相同的行为 - 我做错了什么 - 这应该很容易,不应该吗?
#import "GFTextStore.h"
@implementation GFTextStore
@synthesize textVal = textVal_;
-(void)changeText{
if (!undoMan_) {
undoMan_ = [[[NSApplication sharedApplication] mainWindow] undoManager];
}
NSAttributedString *oldText = [self.textVal copy];
NSString *tempStr = [[oldText string] stringByAppendingFormat:@"\n%@",[[NSCalendarDate date]description]];
NSAttributedString *newText = [[NSAttributedString alloc] initWithString:tempStr];
[self setTextVal:newText];
[undoMan_ registerUndoWithTarget:self
selector:@selector(setTextVal:)
object:oldText];
[undoMan_ setActionName:@"ACTION"];
}
@end
此处无需添加 NSUndoManager,只需让 NSTextView 完成该工作即可。
您只需要确保您正在致电仅更高级别的方法NSTextView 开头为insert…并且不直接设置textView或textStorage的文本/字符串:
[self.textView insertText:newString];
如果您绝对需要使用 setString 或其他较低级别的方法,那么您只需添加处理 textDidChange 委托所需的方法:-shouldChangeTextInRange:替换字符串 and -did更改文本(这是通过 insert... 方法完成的):
if( [self.textView shouldChangeTextInRange:editedRange replacementString:editedString]) {
// do some fancy stuff here…
[self.textView.textStorage replaceCharactersInRange:editedRange
withAttributedString:myFancyNewString];
// … and finish the editing with
[self.textView didChangeText];
}
这会自动让 NSTextView 的 undoManager 启动。我认为 undoManager 正在 shouldChangeTextInRange: 中准备撤消分组,并在 didChangeText: 中调用撤消。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)