【问题标题】:Undo operation with NSUndoManager in rich UITextView (iOS 6)在富 UITextView (iOS 6) 中使用 NSUndoManager 撤消操作
【发布时间】:2012-09-26 08:50:38
【问题描述】:

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

看完NSUndoManager documentation,我尝试了第一种方式:

“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 是模拟粘贴操作。如果可能的话,我宁愿避免这种情况(还没有理由,只是觉得太脏了,以后不回来咬我)。

【问题讨论】:

  • 你确认self.textViewself.textView.attributedTextself.textView.undoManager都不是nil了吗?
  • 是的。 self.textView.attributedText = newValue 实际上是在用户界面中更新的。 textView.undoManager 是类 WebThreadSafeUndoManager 的成员,并且是我的 viewController 的所有生命周期的同一个实例。
  • 我注意到了同样的问题。我可以撤消一些操作,但不能撤消属性字符串替换。找不到解决方法(请参阅stackoverflow.com/questions/12501541/…

标签: uitextview ios6 nsattributedstring nsundomanager uitextinput


【解决方案1】:

我还是有点震惊这行得通。我在这里发布了相同的答案UITextView undo manager do not work with replacement attributed 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];
}

【讨论】:

    猜你喜欢
    • 2011-07-02
    • 2023-03-25
    • 2011-05-03
    • 2011-07-02
    • 2011-03-18
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    • 2011-03-29
    相关资源
    最近更新 更多