iOS -NSUndoManager stops working when some text is appended to a textView

1.2k views Asked by At

So my problem is to make my textView capable of undo/redo action ( I use two buttons to do this ). Reading the doc I discovered that UITextView has a built-in undoManager and his basic usage is really simple. What I've done so far?

I've a viewController (EditorViewController) containing the textView.

in EditorViewcontroller.h

     NSUndoManager *myUndoManager;

in EditorViewController.m --> viewDidLoad

    myUndoManager = [textView undoManager];

as I said two buttons are used to perform undo/redo actions, thos two buttons are located into the inputAccessoryView of the textView, this view is basically a toolbar with several button used to append text to the textView.

I've a method called appendText:

- (IBAction) appendText:(id)sender{

   NSString *contentsToAdd;
   NSMutableString *textViewContent;
   NSRange cursorPosition;
   if ([undoManager canUndo]) {
      NSLog(@"yes canundo");
   }
   switch ([sender tag]) {
      case 0:
        [textView setScrollEnabled:NO];
        contentsToAdd = @"[]";   
        cursorPosition = [textView selectedRange];

        textViewContent = [[NSMutableString alloc] 
                             initWithString:[textView text]];

        [textViewContent insertString:contentsToAdd 
                                      atIndex:cursorPosition.location];

        [textView setText:textViewContent];

        [textViewContent release];
        cursorPosition.location++;
        textView.selectedRange=cursorPosition;

        [textView becomeFirstResponder];
        [textView setScrollEnabled:YES];
        if (![undoManager canUndo]) {
             NSLog(@" can't undo");
         }  
         break;
        // more case following 0..9
        case 10:
         [myUndoManager undo];
         [break];  
        case 11 :
         [myUndoManager redo];
         break;
 }

Now things works well if I write using the keyboard, I mean undo and redo works properly. But when I append some text using the appendText: method, undo and redo aren't performed.If I begin to write again using the keyboard undo and redo are performed(the first element of the undo stack is last text written) It's like if the undo and redo stack are cleared every time I append some text. I hope someone can give me an hint..

1

There are 1 answers

0
appmattus On

You have to call the undo manager telling it what to do when you want to undo. In this undo function you also tell it how to redo your change(s).

I use the following function for undoing:

- (void) undoText:(NSString*)text range:(NSRange)range {
    [[textView.undoManager prepareWithInvocationTarget:self] undoText:[NSString stringWithString:c textView.text] range:textView.selectedRange];
    textView.text = text;
    textView.selectedRange = range;
}

Within your appendText function you then have to do something like the following at the top of it:

[[textView.undoManager prepareWithInvocationTarget:self] undoText:[NSString stringWithString:textView.text] range:textView.selectedRange];
[textView.undoManager setActionName:@"name to appear in undo"];