使用NSUndoManager,如何使用Swift闭包注册撤消 [英] Using NSUndoManager, how to register undos using Swift closures

查看:117
本文介绍了使用NSUndoManager,如何使用Swift闭包注册撤消的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Swift闭包来使用NSLayoutManager.我可以成功注册undo,如下所示:

I am trying to grok how to use NSLayoutManager using Swift closures. I can successfully register an undo as follows:

doThing();
undoManager?.registerUndoWithTarget(self, handler: { _ in
    undoThing();
}
undoManager?.setActionName("do thing")

我当然需要支持redo,这相当于撤消.我可以做到:

Of course I need to support redo which amounts to an undo of an undo. I can do that:

doThing();
undoManager?.registerUndoWithTarget(self, handler: { _ in
    undoThing();

    undoManager?.registerUndoWithTarget(self, handler: { _ in
        doThing();
    }
    undoManager?.setActionName("do thing")
}
undoManager?.setActionName("do thing")

但是现在我需要支持重做的撤消... hmmm ....好的:

But now I need to support an undo of the redo... hmmm.... ok:

doThing();
undoManager?.registerUndoWithTarget(self, handler: { _ in
    undoThing();

    undoManager?.registerUndoWithTarget(self, handler: { _ in
        doThing();

        undoManager?.registerUndoWithTarget(self, handler: { _ in
             undoThing();
        }
        undoManager?.setActionName("do thing")
    }
    undoManager?.setActionName("do thing")
}
undoManager?.setActionName("do thing")

您可以看到它的乌龟一直向下".我如何摆脱这种疯狂?即,在我能找到的所有示例代码中,人们使用代码的选择器版本来注册一种可以撤消自身的方法-这显然与我使用的闭包方法不可行...一个人如何使用闭包版本并获得无限的撤消/重做?

As you can see its "turtles all the way down." How do I escape from this madness? i.e., in all the example code I can find, folks use the selector version of the code to register a method that can undo itself -- this is not obviously doable with the closure method I am using... How does one use the closure version and get unlimited undo/redo?

推荐答案

您要查找的是相互递归.您需要两个函数,每个函数都注册一个到另一个的调用.以下是几种不同的结构方式:

What you're looking for is mutual recursion. You need two functions, each of which registers a call to the other. Here are a couple of different ways to structure it:

  1. doThing()中,注册撤消操作以调用undoThing().在undoThing中,注册撤消操作以调用doThing().那就是:

  1. In doThing(), register the undo action to call undoThing(). In undoThing, register the undo action to call doThing(). That is:

@IBAction func doThing() {
    undoManager?.registerUndoWithTarget(self, handler: { me in
        me.undoThing()
    })
    undoManager?.setActionName("Thing")

    // do the thing here
}

@IBAction func undoThing() {
    undoManager?.registerUndoWithTarget(self, handler: { me in
        me.doThing()
    })
    undoManager?.setActionName("Thing")

    // undo the thing here
}

请注意,除非您用weak捕获,否则不应引用闭包中的self,因为强烈捕获(默认值)可能会形成保留周期.由于您将self作为target传递给撤消管理器,因此它已经为您保留了一个弱引用,并将其(强烈地)传递给了undo块,因此您最好使用该引用而不在以下地方引用self全部都在撤消块中.

Note that you should not refer to self in the closure unless you capture it with weak, because capturing it strongly (the default) may create a retain cycle. Since you're passing self to the undo manager as target, it's already keeping a weak reference for you and passing it (strongly) to the undo block, so you might as well use that and not reference self at all in the undo block.

  1. 将对doThing()undoThing()的调用包装在处理撤消注册的单独函数中,并将用户操作连接到这些新函数:

  1. Wrap the calls to doThing() and undoThing() in separate functions that handle undo registration, and connect user actions to those new functions:

private func doThing() {
    // do the thing here
}

private func undoThing() {
    // undo the thing here
}

@IBAction func undoablyDoThing() {
    undoManager?.registerUndoWithTarget(self, handler: { me in
        me.redoablyUndoThing()
    })
    undoManager?.setActionName("Thing")
    doThing()
}

@IBAction func redoablyUndoThing() {
    undoManager?.registerUndoWithTarget(self, handler: { me in
        me.undoablyDoThing()
    })
    undoManager?.setActionName("Thing")
    undoThing()
}

这篇关于使用NSUndoManager,如何使用Swift闭包注册撤消的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆