使用 UITextView 撤消/重做 (iOS/iPHone)

发布于 2024-09-30 07:00:17 字数 1035 浏览 11 评论 0原文

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

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

// 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. 撤消清除和重做清除工作,但是,然后我再次看到“撤消清除”,但此后就不起作用了。

有什么想法吗?我这样做是错误的吗?

更新:似乎我已经解决了空撤消项问题:当我在调用prepareWithInitationTarget之后设置UITextView的文本时,就会发生这种情况。如果我之前调用它,它就不会发生。有趣的是,如果我不调用prepareWithIn VocationTarget(即,通常,当我设置UITextView的文本时),则空项目不会被推送到撤消堆栈上。

I have a view where a UITextView always has focus. What I want to do is extend the built-in undo/redo behavior to support undo/redo for when I programmatically set the text (e.g., for when I clear it, by setting it to @"").

Since only the firstResponder gets undo/redo events, I thought I'd simply use the UITextView's undoManager property to create my invocations. e.g.,

// 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:@""];  
    }
}

Unfortunately, this is not working. It:

  1. Introduces an empty item into the undo stack ("Undo")
  2. The "Undo Clear" gets added after that item (if I tap "Undo", I see "Undo Clear")
  3. Undo Clear and Redo Clear work, however, then I see "Undo Clear" again and it doesn't work from there on.

Any ideas? Am I approaching this wrong?

Update: It seems like I've figured out the empty undo item issue: it happens when I set the text of the UITextView after I've called prepareWithInvocationTarget. If I call it before, it doesn't happen. Funny thing is, the empty item isn't pushed onto the undo stack if I don't call prepareWithInvocationTarget (i.e., normally, when I set the text of a UITextView).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

高冷爸爸 2024-10-07 07:00:17

好的,弄清楚了:

#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];
}

它现在正在正常工作。

OK, figured it out:

The issue with #1 is as outlined in the update to my original post.

Issues #2 and #3 were just me using the NSUndoManager incorrectly. My final unClear method (which gets called on undos is as follows:

-(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];
}

It's working as it should now.

淡笑忘祈一世凡恋 2024-10-07 07:00:17

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

You can change your textview to whatever text you want and preserve undo and redo manager's memory stacks. self.content is 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
}

}

//just one, my method I created

-(void) undoClearBlablabla:(NSString*) text
    {
        [[self.content.undoManager prepareWithInvocationTarget:self] undoClear:self.content.text];
        [self.content setText:text];
    }
谎言 2024-10-07 07:00:17

我不知道您正在使用多少个文​​本字段,尽管 textBackup 没有被 prepareWithInitationTarget 保留: 几次清除后它如何仍然在撤消堆栈中?似乎在第一个之后它可能仍然存在,但在第二个之后或自动释放池刷新之后已经不存在了。

I'm not sue how many Text Fields you are working with, though textBackup is not getting retained by prepareWithInvocationTarget: How is it still in the Undo Stack several clear's later? Seems like it might still be there after the first one, though not after the 2nd one or after the Autorelease pool flushes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文