Отменить/повторить с помощью UITextView (iOS/iPHone)

У меня есть представление, в котором UITextView всегда имеет фокус. Что я хочу сделать, так это расширить встроенное поведение отмены/повтора для поддержки отмены/повтора, когда я программно устанавливаю текст (например, когда я очищаю его, устанавливая для него значение @"").

Поскольку только firstResponder получает события отмены/возврата, я подумал, что просто использую свойство undoManager UITextView для создания своих вызовов. например.,

// Before clearing the text...
[[self.myTextView.undoManager prepareWithInvocationTarget:self] undoClear:self.myTextView.text]; 
[self.myTextView.undoManager setActionName:@"Clear"];

// ...

-(void)undoClear:(NSString *)textToRestore
{
    self.myTextView.text = textToRestore;
    if ([self.myTextView.undoManager isUndoing])
    {
      // Prepare the redo.
      [[self.myTextView.undoManager prepareWithInvocationTarget:self] undoClear:@""];  
    }
}

К сожалению, это не работает. Это:

  1. Вводит пустой элемент в стек отмены («Отмена»)
  2. После этого элемента добавляется «Отменить очистку» (если я нажму «Отменить», я увижу «Отменить очистку»)
  3. Однако Undo Clear и Redo Clear работают, затем я снова вижу «Undo Clear», и с этого момента он не работает.

Любые идеи? Я подхожу к этому неправильно?

Обновление: кажется, я разобрался с проблемой пустого элемента отмены: это происходит, когда я устанавливаю текст UITextView после вызова prepareWithInvocationTarget. Если я назову это раньше, этого не произойдет. Забавно то, что пустой элемент не помещается в стек отмены, если я не вызываю prepareWithInvocationTarget (т. е. обычно, когда я устанавливаю текст UITextView).


person Aral Balkan    schedule 01.11.2010    source источник


Ответы (3)


Хорошо, разобрался:

Проблема с № 1 описана в обновлении моего исходного сообщения.

Проблемы № 2 и № 3 заключались только в том, что я неправильно использовал NSUndoManager. Мой последний метод unClear (который вызывается при отмене) выглядит следующим образом:

-(void)undoClear:(NSString *)textToRestore
{   
    NSString *textBackup = [self.myTextView.text copy];

    self.myTextView.text = textToRestore;

    if ([self.myTextView.undoManager isUndoing])
    {
        // Prepare the redo.
        [[self.myTextView.undoManager prepareWithInvocationTarget:self] undoClear:@""];     
    }
    else if ([self.myTextView.undoManager isRedoing])
    {
        [[self.myTextView.undoManager prepareWithInvocationTarget:self] undoClear:textBackup];
    }

    [textBackup release];
}

Сейчас работает как надо.

person Aral Balkan    schedule 01.11.2010
comment
привет, я думаю, что моя проблема похожа на это, не могли бы вы сказать мне, в каком методе вы вызываете метод undoClear? Спасибо - person R. Dewi; 26.01.2011
comment
@Risma: непосредственно перед тем, как вы установите содержимое textView. - person Anh; 16.03.2011
comment
Одна проблема, с которой я столкнулся при попытке реализовать этот метод, заключается в том, что все предыдущие отмены стираются. Так что, если они печатают, а затем дважды нажимают «Очистить» и хотят отменить, это просто вернет их к тому, что было в их текстовом содержании раньше. - person philipkd; 07.09.2011
comment
Вместо приведенного выше, которое касается только «очистки» поля, следующее будет работать со стеком отмены/возврата поля. Просто вызовите '[self changeTextValue: @new value]' для всех ваших изменений: - (void) changeTextValue: (NSString*) newVal { NSString *oldNotes = [self.txtViewNotes.text copy]; [self.txtViewNotes setText: newVal]; [[self.txtViewNotes.undoManager prepareWithInvocationTarget:self] changeTextValue: oldNotes]; } - person strange; 16.05.2014

Вы можете изменить свое текстовое представление на любой текст, который вы хотите, и сохранить стеки памяти менеджера отмены и повтора. self.content — это UITextView.

-(void) yourClearAllButtonIsPressed
{
    [[self.content.undoManager prepareWithInvocationTarget:self] undoClear:self.content.text];
    [self.content setText:@""];//Or something else you want to change your textview to
}

}

//только один, мой метод, который я создал

-(void) undoClearBlablabla:(NSString*) text
    {
        [[self.content.undoManager prepareWithInvocationTarget:self] undoClear:self.content.text];
        [self.content setText:text];
    }
person coolcool1994    schedule 30.10.2013
comment
Что, почему ты -1 это? Вы можете объяснить? Это очень хорошее рабочее решение для меня. - person coolcool1994; 10.02.2014
comment
Да, пожалуйста, объясните, почему кто-то это -1, это выглядит правильно! - person strange; 12.05.2014

Я не знаю, с каким количеством текстовых полей вы работаете, хотя textBackup не сохраняется prepareWithInvocationTarget:. Как оно все еще находится в стеке отмен через несколько очисток? Похоже, что он все еще может быть там после первого, но не после второго или после сброса пула Autorelease.

person scooter133    schedule 20.03.2012