5

我想更改富 UITextView (iOS 6) 的部分或全部属性文本,并允许用户撤消更改。

阅读NSUndoManager 文档后,我尝试了第一种方法:

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

我希望撤消操作很简单:
声明此方法:

- (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];
    }
}

通过调用更改我的 UITextView 中的文本:

[self setAttributedStringToTextView:mutableAttributedString];

但是在这样做之后,NSUndoManager 说它无法撤消。

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




所以我尝试了第二种方法:

“Invocation-based undo” which uses an NSInvocation object.

声明:

- (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];
    }
}

并更改文本:

[self setMyTextViewAttributedString:mutableAttributedString];

之后,NSUndoManager 也表示无法撤消。

为什么?

请注意,当触发将更改属性文本的代码时,用户正在编辑 UITextView。




一种解决方法是直接通过 UITextInput 协议方法替换文本。下面的方法还是挺方便的,但是我还没有找到 NSAttributedString 的等价物。我错过了吗?

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

这里建议的 hack 是模拟粘贴操作。如果可能的话,我宁愿避免这种情况(还没有理由,只是觉得太脏了,以后不回来咬我)。

4

1 回答 1

1

我还是有点震惊这行得通。我在这里发布了相同的答案UITextView undo manager do not work with replacement attributes string (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];
}
于 2014-06-17T13:14:24.097 回答