【问题标题】:Undo/redo with a UITextView (iOS/iPHone)使用 UITextView 撤消/重做 (iOS/iPHone)
【发布时间】:2011-05-03 11:41:32
【问题描述】:

我有一个 UITextView 始终具有焦点的视图。我想要做的是扩展内置的撤消/重做行为以支持我以编程方式设置文本时的撤消/重做(例如,当我清除它时,通过将其设置为 @"")。

由于只有 firstResponder 获得撤消/重做事件,我想我只需使用 UITextView 的 undoManager 属性来创建我的调用。例如,

// 清除文本之前...
[[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])
    {
      // 准备重做。
      [[self.myTextView.undoManager prepareWithInvocationTarget:self] undoClear:@""];
    }
}

很遗憾,这不起作用。它:

  1. 将一个空项引入撤消堆栈(“撤消”)
  2. 在该项目之后添加了“撤消清除”(如果我点击“撤消”,我会看到“撤消清除”)
  3. 撤消清除和重做清除工作,但是,然后我再次看到“撤消清除”,它从那里不起作用。

有什么想法吗?我是不是搞错了?

更新:似乎我已经解决了空撤消项问题:它发生在我设置 UITextView 的文本之后,我调用了 prepareWithInvocationTarget。如果我之前调用它,它不会发生。有趣的是,如果我不调用 prepareWithInvocationTarget(即,通常,当我设置 UITextView 的文本时),空项目不会被推入撤消堆栈。

【问题讨论】:

    标签: iphone uitextview undo nsundomanager redo


    【解决方案1】:

    好的,想通了:

    #1 的问题在我的原始帖子的更新中有所概述。

    问题 #2 和 #3 只是我错误地使用了 NSUndoManager。我的最终 unClear 方法(在撤消时调用如下:

    -(void)undoClear:(NSString *)textToRestore
    {
        NSString *textBackup = [self.myTextView.text 复制];
    
        self.myTextView.text = textToRestore;
    
        if ([self.myTextView.undoManager isUndoing])
        {
            // 准备重做。
            [[self.myTextView.undoManager prepareWithInvocationTarget:self] undoClear:@""];
        }
        else if ([self.myTextView.undoManager isRedoing])
        {
            [[self.myTextView.undoManager prepareWithInvocationTarget:self] undoClear:textBackup];
        }
    
        [文本备份发布];
    }

    它现在可以正常工作了。

    【讨论】:

    • 嗨,我想我的问题与此类似,你能告诉我,你用什么方法调用 undoClear 方法?谢谢
    • @Risma:就在你设置 textView 的内容之前。
    • 在尝试实现此方法时,我遇到的一个问题是所有先前的撤消都被删除了。因此,如果他们正在打字,然后点击“清除”并想要撤消两次,它只会让他们恢复到之前的文本内容。
    • 上面只处理“清除”字段,下面将处理字段的撤消/重做堆栈。只需调用 '[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]; }
    【解决方案2】:

    您可以将您的文本视图更改为您想要的任何文本,并保留撤消和重做管理器的内存堆栈。 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];
        }
    

    【讨论】:

    • 你为什么要-1这个?你可以解释吗?这对我来说是一个很好的工作解决方案。
    • 是的,请解释为什么有人会 -1 这个,这看起来是正确的!
    【解决方案3】:

    尽管textBackup 没有被prepareWithInvocationTarget: 保留,但我不知道您正在使用多少个文​​本字段@ 它是如何在数次清除之后仍在撤消堆栈中的?似乎它可能在第一个之后仍然存在,但不是在第二个之后或 Autorelease 池刷新之后。

    【讨论】:

      猜你喜欢
      • 2011-03-18
      • 2023-03-02
      • 1970-01-01
      • 2018-11-04
      • 2020-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-19
      相关资源
      最近更新 更多