【问题标题】:Difficulty implementing NSUndoManager redo functionNSUndoManager 重做功能难以实现
【发布时间】:2011-11-23 21:46:25
【问题描述】:

我正在尝试在我的 iOS 应用中实现 NSUndoManager。我让撤消功能工作,但不是重做部分。我对 iOS 开发很陌生,这是我第一次使用NSUndoManager,所以这可能是微不足道的。

我的应用程序是一个绘画/笔记应用程序,我有一个撤消/重做堆栈,其中最后十个 UIImages(我不知道这是否是最有效的方式)在一个数组中。当用户对当前图像进行更改时,旧图像被压入堆栈,如果数组已经有十个对象,则删除数组中的第一个图像。我有一个int 实例变量,用于跟踪数组中的对象并确保显示正确的图像。我的代码如下所示:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    if (oldImagesArrays.count >= 10) {
        [oldImagesArrays removeObjectAtIndex:0];
    }
    UIImage * currentImage = pageView.canvas.image;
    if (currentImage != nil) {
        [oldImagesArrays addObject:currentImage];
        undoRedoStackIndex = oldImagesArrays.count -1;
    }
    [...]
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

    UIImage * currentImage = [oldImagesArrays lastObject];
    if (currentImage != pageView.canvas.image) {
        [undoManager registerUndoWithTarget:self selector:@selector(resetImage)  
        object:currentImage];
    }
}

// Gets called when the undo button is clicked
- (void)undoDrawing
{
    [undoManager undo];
    [undoManager registerUndoWithTarget:self 
                           selector:@selector(resetImage)
                             object:pageView.canvas.image];
    undoRedoStackIndex--;
}

// Gets called when the redo button is clicked
- (void)redoDrawing
{
    [undoManager redo];
    undoRedoStackIndex++;
}

- (void)resetImage
{
    NSLog(@"Hello"); // This NSLog message only appears when I click undo.
    pageView.canvas.image = [oldImagesArrays objectAtIndex:undoRedoStackIndex];
}

当我单击撤消或重做按钮时 resetImage 应该被调用,并将当前图像设置为我的图像堆栈中的下一个或上一个对象(undoRedoStackIndex 的当前值),这只会发生在我单击撤消,但不重做。

解决方案 && ||更好的方法将不胜感激。

【问题讨论】:

  • @JoshCaswell 我已经对我的问题进行了一些澄清。

标签: objective-c ios cocoa-touch nsundomanager


【解决方案1】:

您不需要跟踪更改,这就是撤消管理器的用途。

像这样创建一个可撤销的方法:

- (void)setImage:(UIImage*)image
{
    if (_image != image)
    {
        [[_undoManager prepareWithInvocationTarget:self] setImage:_image]; // Here we let know the undo managed what image was used before
        [_image release];
        _image = [image retain];

        // post notifications to update UI
    }
}

就是这样。要撤消更改,只需调用[_undoManager undo],重做调用[_undoManager redo]。当您告诉撤消管理器撤消时,它将使用旧图像调用此方法。如果您使用自定义按钮进行撤消操作,您可以使用[NSUndoManager canUndo] 等进行验证。

撤消操作的次数没有限制。如果您需要在某些时候清理撤消堆栈,只需调用removeAllActions 方法。

【讨论】:

  • 谢谢你,让它工作。怀疑这比我做的容易。谢谢。 // 安德斯
  • @Davyd 嗨,你能帮我这个:) “发布通知以更新 UI”如何更新 UIImage?
  • 我发布的带有撤消管理器的方法应该在数据模型中使用。这就是为什么我对发布通知发表评论的原因。例如:[[NSNotificationCentre defaultCentre] postNotification:XXMyDataModelDidChangeImageNotification object:self]。这意味着在某个地方应该有一个视图控制器,其中包含一个实际显示图像的视图 (UIImageView)。这个视图控制器应该订阅来自数据模型的通知,并在收到通知时更新视图。或者,可以使用 KVO。我希望这会有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-08
  • 2014-04-01
  • 1970-01-01
  • 2019-11-12
  • 2011-05-01
  • 1970-01-01
相关资源
最近更新 更多