使用NSUndoManager,如何使用Swift闭包注册撤消 [英] Using NSUndoManager, how to register undos using Swift closures
问题描述
我正在尝试使用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:
-
在
doThing()
中,注册撤消操作以调用undoThing()
.在undoThing
中,注册撤消操作以调用doThing()
.那就是:
In
doThing()
, register the undo action to callundoThing()
. InundoThing
, register the undo action to calldoThing()
. 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.
-
将对
doThing()
和undoThing()
的调用包装在处理撤消注册的单独函数中,并将用户操作连接到这些新函数:
Wrap the calls to
doThing()
andundoThing()
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屋!