5

リッチ 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"




だから私は2番目の方法を試しました:

“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

ここで提案されているハックは、貼り付け操作をシミュレートすることです。可能であれば、これを避けたいと思います(理由はまだありません。後で噛まれないようにするには、あまりにも汚いと感じているだけです)。

4

1 に答える 1

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];
}
于 2014-06-17T13:14:24.097 に答える