如何在UITextView中用NSUndoManager支持replace文本?

我希望能够以编程方式replaceUITextView中的某些文本,所以我将此方法编写为UITextView类别:

- (void) replaceCharactersInRange:(NSRange)range withString:(NSString *)newText{ self.scrollEnabled = NO; NSMutableString *textStorage = [self.text mutableCopy]; [textStorage replaceCharactersInRange:range withString:newText]; //replace text but undo manager is not working well [[self.undoManager prepareWithInvocationTarget:self] replaceCharactersInRange:NSMakeRange(range.location, newText.length) withString:[textStorage substringWithRange:range]]; NSLog(@"before replacing: canUndo:%d", [self.undoManager canUndo]); //prints YES self.text = textStorage; NSLog(@"after replacing: canUndo:%d", [self.undoManager canUndo]); //prints NO if (![self.undoManager isUndoing])[self.undoManager setActionName:@"replace characters"]; [textStorage release]; //new range: range.location = range.location + newText.length; range.length = 0; self.selectedRange = range; self.scrollEnabled = YES; } 

它的工作,但NSUndoManager停止工作(它似乎被重置)刚做self.text=textStorage我已经find一个私人的API: -insertText:(NSString *) ,可以做这项工作,但谁知道,如果苹果将批准我应用程序,如果我使用它。 有没有办法让文本replaceUITextView与NSUndoManager支持? 或者,也许我在这里错过了什么?

实际上没有任何黑客或自定义类别来完成这个任务的理由。 您可以使用内置的UITextInput协议方法replaceRange:withText: 要插入文本,你可以简单地做:

 [textView replaceRange:textView.selectedTextRange withText:replacementText]; 

这适用于iOS 5.0。 撤消自动工作,没有奇怪的滚动问题。

在偶然发现了这个问题后,我终于find了一个令人满意的解决scheme。 这有点俗气,但它的工作就像一个魅力。 这个想法是使用UITextView提供的工作副本和粘贴支持! 我想你可能会感兴趣:

 - (void)insertText:(NSString *)insert { UIPasteboard *pboard = [UIPasteboard generalPasteboard]; // Clear the current pasteboard NSArray *oldItems = [pboard.items copy]; pboard.items = nil; // Set the new content to copy pboard.string = insert; // Paste [self paste: nil]; // Restore pasteboard pboard.items = oldItems; [oldItems release]; } 

编辑:当然,您可以自定义此代码插入文本在文本视图中的任何位置。 在调用paste之前,只需设置selectedRange

不应该是

 [[self.undoManager prepareWithInvocationTarget:self] replaceCharactersInRange:NSMakeRange(range.location, newText.length) withString:[self.text substringWithRange:range]]; 

你可能可以删除可变的string,只是做,

 self.text = [self.text stringByReplacingCharactersInRange:range withString:newText];