Как я могу заменить текст в UITextView с поддержкой NSUndoManager? - PullRequest
10 голосов
/ 21 июня 2011

Я хочу иметь возможность заменять некоторый текст в 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 одобрить мое приложение, если я его использую.Есть ли способ заменить текст в UITextView с поддержкой NSUndoManager?А может я что-то здесь упускаю?

Ответы [ 4 ]

6 голосов
/ 26 апреля 2012

На самом деле нет никаких оснований для каких-либо взломов или пользовательских категорий для достижения этой цели. Вы можете использовать встроенный метод протокола UITextInput replaceRange:withText:. Для вставки текста вы можете просто сделать:

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

Это работает с iOS 5.0. Отмена работает автоматически, и нет никаких странных проблем с прокруткой.

4 голосов
/ 08 июля 2011

После того, как я наткнулся на эту проблему и получил седые волосы, я наконец нашел удовлетворительное решение.Это немного липко, но работает как шарм.Идея состоит в том, чтобы использовать рабочую поддержку копирования и вставки, которую предлагает 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];
}

РЕДАКТИРОВАТЬ: Конечно, вы можете настроить этот код для вставки текста в любой позиции в текстовом представлении.Просто установите selectedRange перед вызовом paste.

1 голос
/ 21 июня 2011

Разве это не должно быть

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

И вы, вероятно, можете удалить изменяемую строку и просто сделать,

self.text = [self.text stringByReplacingCharactersInRange:range withString:newText];
0 голосов
/ 20 ноября 2018

У меня были проблемы с этим в течение долгого времени.Я наконец понял, что вы должны убедиться, что регистрировали операцию отмены ПЕРЕД внесением каких-либо изменений в ваше текстовое хранилище.

...