Cancel operation with NSUndoManager in rich UITextView (iOS 6)

I want to change some or all of the text attribute of a rich UITextView (iOS 6) and allow the user to undo the change.

After reading the NSUndoManager documentation , I tried the first method:

"Simple undo" based on a simple selector with a single object argument.

I expected the undo operation to be as simple as:
Declare this method:

- (void)setAttributedStringToTextView:(NSAttributedString *)newAttributedString {

     NSAttributedString *currentAttributedString = self.textView.attributedText;

    if (! [currentAttributedString isEqualToAttributedString:newAttributedString]) {
         [self.textView.undoManager registerUndoWithTarget:self
                                    selector:@selector(setAttributedStringToTextView:)
                                      object:currentAttributedString];
         [self.textView.undoManager setActionName:@"Attributed string change"];
         [self.textView setAttributedText:newAttributedString];
    }
}

Change the text in my UITextView by calling:

[self setAttributedStringToTextView:mutableAttributedString];

But after that, NSUndoManager says that it cannot cancel.

NSLog(@"Can undo: %d", [self.textView.undoManager canUndo]);
// Prints: "Can undo: 0"




So I tried the second option:

"Invocation-based undo" which uses an NSInvocation object.

Declare this:

- (void)setMyTextViewAttributedString:(NSAttributedString *)newAttributedString {

        NSAttributedString *currentAttributedString = [self.textView attributedText];
    if (! [currentAttributedString isEqualToAttributedString:newAttributedString]) {
        [[self.textView.undoManager prepareWithInvocationTarget:self]
         setMyTextViewAttributedString:currentAttributedString];
        [self.textView.undoManager setActionName:@"Attributed string change"];
        [self.textView setAttributedText:newAttributedString];
    }
}

and change the text with:

[self setMyTextViewAttributedString:mutableAttributedString];

After that, NSUndoManager also says that it cannot cancel.

Why?

Note that the user edits the UITextView when running code that changes the attribute text.




UITextInput. , NSAttributedString. ?

- (void)replaceRange:(UITextRange *)range withText:(NSString *)text

- . , ( , , ).

+5
1

, . UITextView undo (iOS 6).

- (void)applyAttributesToSelection:(NSDictionary*)attributes {
    UITextView *textView = self.contentCell.textView;

    NSRange selectedRange = textView.selectedRange;
    UITextRange *selectedTextRange = textView.selectedTextRange;
    NSAttributedString *selectedText = [textView.textStorage attributedSubstringFromRange:selectedRange];

    [textView.undoManager beginUndoGrouping];
    [textView replaceRange:selectedTextRange withText:selectedText.string];
    [textView.textStorage addAttributes:attributes range:selectedRange];
    [textView.undoManager endUndoGrouping];

    [textView setTypingAttributes:attributes];
}
+1

All Articles