[英]Using NSUndoManager, how to register undos using Swift closures
I am trying to grok how to use NSLayoutManager
using Swift closures. 我试图了解如何使用Swift闭包使用
NSLayoutManager
。 I can successfully register an undo
as follows: 我可以成功注册
undo
,如下所示:
doThing();
undoManager?.registerUndoWithTarget(self, handler: { _ in
undoThing();
}
undoManager?.setActionName("do thing")
Of course I need to support redo
which amounts to an undo of an undo. 当然我需要支持
redo
,这相当于撤消撤消。 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")
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?
我如何摆脱这种疯狂? ie, 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:
以下是构建它的几种不同方法:
In doThing()
, register the undo action to call undoThing()
. 在
doThing()
,注册撤消操作以调用undoThing()
。 In undoThing
, register the undo action to call doThing()
. 在
undoThing
,注册撤消操作以调用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 }
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. 请注意,你不应该是指
self
的封闭,除非你抓住它weak
,因为它捕捉强(默认值)可以创建一个保留周期。 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. 由于您将
self
作为target
传递给撤消管理器,因此它已经为您保留了弱引用并将其(强烈地)传递给撤消块,因此您可以使用它而不是在撤消块中引用self
。
Wrap the calls to doThing()
and undoThing()
in separate functions that handle undo registration, and connect user actions to those new functions: 将
doThing()
和undoThing()
的调用doThing()
在处理撤销注册的单独函数中,并将用户操作连接到这些新函数:
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() }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.