10

我希望能够以编程方式替换 UITextView 中的一些文本,所以我将此方法编写为 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我找到一个私有 API 之后就停止工作(它似乎被重置):-insertText:(NSString *)它可以完成这项工作,但谁知道如果我使用它,Apple 是否会批准我的应用程序。有什么方法可以用 NSUndoManager 支持在 UITextView 中替换文本?或者我在这里遗漏了什么?

4

4 回答 4

7

实际上没有理由让任何黑客或自定义类别来实现这一点。您可以使用内置的 UITextInput 协议方法replaceRange:withText:。要插入文本,您只需执行以下操作:

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

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

于 2012-04-26T18:26:46.510 回答
4

在偶然发现这个问题并让它变白之后,我终于找到了一个令人满意的解决方案。这有点俗气,但它确实像一个魅力。这个想法是使用 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];
}

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

于 2011-07-08T09:57:18.820 回答
1

难道不应该

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

你可能可以删除可变字符串,然后做,

self.text = [self.text stringByReplacingCharactersInRange:range withString:newText];
于 2011-06-21T03:07:37.173 回答
0

很长一段时间以来,我一直在为此烦恼。我终于意识到,在对文本存储进行任何更改之前,您必须确保注册了撤消操作。

于 2018-11-20T16:01:55.470 回答