0

私はUITextView書式設定ツールバーを持っています。「太字」ボタンを押すと、テキスト/選択が変更され、操作がテキスト ビューの に登録されますNSUndoManager

元に戻そうとするrestoreText:と、アプリを強制終了するまで何度も呼び出されます

サンプルコード:

- (void)bold {
    NSRange range = self.textView.selectedRange;
    NSRange oldRange = range;
    NSString *oldText = self.textView.text;
    NSString *selection = [self.textView.text substringWithRange:range];
    self.textView.scrollEnabled = NO;
    self.textView.text = [self.textView.text stringByReplacingCharactersInRange:range
                                                           withString:[NSString stringWithFormat:@"<b>%@</b>", selection]];
    self.textView.scrollEnabled = YES;
    if (range.length == 0) {                // If nothing was selected
        range.location += 3; // Place selection between tags
    } else {
        range.location += range.length + 7; // Place selection after tag
        range.length = 0;
    }
    self.textView.selectedRange = range;
    [[self.textView.undoManager prepareWithInvocationTarget:self] restoreText:oldText withRange:oldRange];
    [self.textView.undoManager setActionName:@"bold"];
}

- (void)restoreText:(NSString *)text withRange:(NSRange)range {
    NSLog(@"restoreText:%@ %@",text, [NSNumber numberWithBool:[self.textView.undoManager isUndoing]]);
    NSString *oldText = self.textView.text;
    NSRange oldRange = self.textView.selectedRange;
    self.textView.scrollEnabled = NO;
    self.textView.text = text;
    self.textView.scrollEnabled = YES;
    self.textView.selectedRange = range;
    [[self.textView.undoManager prepareWithInvocationTarget:self] restoreText:oldText withRange:oldRange];
}

そしてコンソール:

2012-10-04 18:10:14.207 undotest[8861:c07] restoreText: 1
2012-10-04 18:10:14.633 undotest[8861:c07] restoreText:<b></b> 0
2012-10-04 18:10:15.117 undotest[8861:c07] restoreText: 0
2012-10-04 18:10:15.589 undotest[8861:c07] restoreText:<b></b> 0
2012-10-04 18:10:16.017 undotest[8861:c07] restoreText: 0
2012-10-04 18:10:16.557 undotest[8861:c07] restoreText:<b></b> 0

[self.textView.undoManager isUndoing]で呼び出しを登録する前にチェックしようとしましrestoreText:withRange:たが、クラッシュします:

2012-10-04 18:10:49.297 undotest[8904:c07] restoreText: 1
2012-10-04 18:10:53.412 undotest[8904:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '_endUndoGroupRemovingIfEmpty:: WebThreadSafeUndoManager 0x76551e0 is in invalid state, endUndoGrouping called with no matching begin
'

このコードは iOS5 では機能していましたが、iOS6 では機能しなくなりました。Apple にバグを報告しましたが、何か問題があるかどうかわかりません

4

2 に答える 2

0

単純な取り消しでも、UITextViewインスタンスに同じことが起こります。これはバグである必要があり、UITextViewに元に戻す機能を自分で実装することはできなくなります。誰かがiOS6UITextViewに元に戻る機能を正常に実装したのだろうか...

または、代わりにreplaceRange:withText:(TextInput Protocol)を使用して、UITextViewに元に戻す機能を実装することにしました。少なくとも、テキストをそのメソッドに置き換えて元に戻すことができます。そのための取り消しアクションを自分で登録する必要はありません。そのメソッドは自動的にそれを行います。

于 2012-10-08T15:58:33.833 に答える
0

私は同じ問題を抱えていました.textViewのテキストにアクセスすると、メソッドを繰り返し呼び出してクラッシュするなど、奇妙な動作が発生することがわかりました。

textView.text=@"" //this crashes

これはreplaceRange:withText:、user1263865 の提案に従って使用することで解決できます。元に戻す/やり直しを処理するアクションをカスタマイズする場合は、アクションを登録できますが、テキストを変更する部分はスキップできますreplaceRange:withText:

たとえば、textView のテキストをクリアするクリア テキスト関数とカスタム メッセージ オブジェクトを作成したい場合は、ユーザーがアクションを元に戻すときにそれを復元します。

-(void) clearEditText {
    //Register undo
    [[textView.undoManager prepareWithInvocationTarget:self] undoClearEditTextWithMessage:[self.message retain]];
    //message is retained because undo manager will not retain, it will be released when user undo.

    // Clear text field
    UITextPosition *beginning = textView.beginningOfDocument;
    UITextPosition *end= textView.endOfDocument;
    UITextRange *textRange = [textView textRangeFromPosition:beginning toPosition:end];
    [textView replaceRange:textRange withText:@""];

    self.message = /*new message*/;
}
-(void) undoClearEditTextWithMessage:(Message*)restoreMessage {
    //Register redo
    [[textView.undoManager prepareWithInvocationTarget:self] undoClearEditTextWithMessage:[self.message retain]];

    self.message = restoreMessage;

    [restoreMessage release];
    //message is released because it is retained when it is added to undo manager.
}
于 2012-12-03T19:47:14.247 に答える