- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
如何在 Swift 中使用 UndoManager
(以前的 NSUndoManager
)?
这是我尝试复制的 Objective-C 示例:
[[undoManager prepareWithInvocationTarget:self] myArgumentlessMethod];
然而,Swift 似乎没有 NSInvocation
,这(表面上)意味着我无法在它未实现的 undoManager
上调用方法。
我在 Swift 中尝试过基于对象的版本,但它似乎让我的 Playground 崩溃了:
undoManager.registerUndoWithTarget(self, selector: Selector("myMethod"), object: nil)
但是它似乎崩溃了,即使我的对象接受类型为 AnyObject?
的参数
在 Swift 中执行此操作的最佳方法是什么?有没有办法避免使用基于对象的注册发送不必要的对象?
最佳答案
OS X 10.11+/iOS 9+ 更新
(在 Swift 3 中同样有效)
OS X 10.11 和 iOS 9 引入了一个新的 NSUndoManager
函数:
public func registerUndoWithTarget<TargetType>(target: TargetType, handler: TargetType -> ())
示例
想象一个 View Controller (本例中的 self
,类型为 MyViewController
)和一个具有存储属性 的
。Person
模型对象姓名
func setName(name: String, forPerson person: Person) {
// Register undo
undoManager?.registerUndoWithTarget(self, handler: { [oldName = person.name] (MyViewController) -> (target) in
target.setName(oldName, forPerson: person)
})
// Perform change
person.name = name
// ...
}
警告
如果您发现您的撤消不是(即,它执行但似乎什么都没发生,就好像撤消操作已运行但它仍然显示您想要撤消的值从) ,请仔细考虑执行撤消处理程序闭包时的实际值(上例中的旧名称)。
您要恢复到的任何旧值(如本例中的oldName
)必须在捕获列表中照原样捕获。也就是说,如果上面示例中闭包的单行改为:
target.setName(person.name, forPerson: person)
...撤消不会工作,因为在执行撤消处理程序闭包时,person.name
已设置为新 名称,这意味着当用户执行撤消操作时,您的应用(在上面的简单示例中)似乎什么都不做,因为它将名称设置为其当前值,这当然不会撤消任何操作。
捕获列表([oldName = person.name]
)在签名((MyViewController) -> ()
)之前声明了oldName
引用 person.name
,因为它是 闭包声明时,而不是执行时。
关于捕获列表的更多信息
有关捕获列表的更多信息,请阅读 Erica Sadun 的一篇题为 Swift: Capturing references in closures 的精彩文章.还值得关注她提到的保留周期问题。此外,尽管她没有在她的文章中提及它,但我在上面使用的捕获列表中的内联声明来自 Swift 2.0 的 Swift 编程语言一书的表达式部分。
其他方式
当然,更详细的方法是在调用 registerUndoWithTarget(_:handler:)
之前让 let oldName = person.name
,然后oldName
在范围内自动捕获。我发现捕获列表方法更易于阅读,因为它就在处理程序中。
我也完全没有让 registerWithInvocationTarget()
很好地处理非 NSObject
类型(如 Swift enum
)作为参数。在后一种情况下,请记住,调用目标不仅应该继承自NSObject
,而且您在该调用目标上调用的函数的参数应该也一样。或者至少是桥接 Cocoa 类型的类型(如 String
和 NSString
或 Int
和 NSNumber
等。 ).但是也有调用目标没有被保留的问题,我无法解决。此外,使用闭包作为完成处理程序要快捷得多。
收尾(明白吗?)
弄清楚这一切花了我几个小时的时间,我几乎无法控制愤怒(我的 Apple Watch 可能对我的心率有些担忧 - “tap-tap! 伙计......倾听你的心,你可能想要冥想或其他东西”)。我希望我的痛苦和牺牲有所帮助。 :-)
关于ios - 如何在 Swift 中注册 UndoManager?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24326984/
HTML5 规范提到了一个 UndoManager,它可用于查询用户编辑过的文档的先前状态 (http://www.whatwg.org/specs/web-apps/current-work/#un
我使用 UndoManager在我的 Swing 应用程序中。如果在 UndoManager 上调用了 undo()、redo()、addEdit() 或其他方法,Undo 和 Redo 按钮最终必须
我有 3 个 MOC。 MainThread MOC 显示内容(使用 undomanager) 后台保存 MOC 以将数据保存到光盘(连接到存储) Backgorund-update MOC 从服务器
我正在使用 UndoManager 来捕获我的 JTextArea 中的更改。 setText() 方法会删除所有内容,然后粘贴文本。当我撤消时,我首先看到一个空白区域,然后它会显示它之前的文本。 如
我对 ACE 很陌生编辑器和 javascript 一般情况下,除了以下内容之外,我已经设法实现了大部分我想要的: 我想启用或禁用“保存”按钮,具体取决于是否对文档进行了未完成的修改,并且我已尝试通过
我希望能够从我的文档模型中访问 UndoManager,这样我就可以在模型中注册撤消操作: // Assume I've extended MyDocument to conform to Refer
我有一个名为 appointment 的 NSManagedObject,我编辑了它的属性。如果我的用户按下取消,我想撤消所有这些编辑。 如果我这样做(示例代码) [[appointment mana
使用 ACE Editor , 它看起来好像使用 editor.getSession().getUndoManager() 和一个已经用 editor.setSession() 设置的 session
我有一个 JTextArea 和一个 JComboBox 允许我循环浏览各种打开的文件 - JTextArea 的内容随着我的选择而改变一个不同的文件。我试图为每个文件维护一个不同的撤消缓冲区,并为每
我正在尝试在我的模型中实现撤消/重做。所以我让我的模型类成为 NSResponder 的子类,然后实现了以下内容: 注意:此代码是根据评论后的更多研究编辑的 func setAnnotations(_
我正在努力向使用 undoManager 的 Swift 库添加一些测试。在库的演示中,将以下打印添加到 viewDidAppear: 会导致打印 NSUndoManagerObject。 overr
我对如何在 Firefox 中使用 undoManager 有点困惑。根据Mozilla , Firefox 20 现在支持它,但我不知道在哪里。我已经在 document、Objects 等下进行了
我想在我的应用程序中应用撤消和重做操作。我阅读了苹果文档并用谷歌搜索了它,但没有得到正确的解决方案。在我的应用程序中,我在 UIImage 上应用了很多图像操作,我想存储每个状态并相应地应用 Undo
我将以下代码用于核心数据单例。下面是我的代码。 (基于 NachoMan 的 blog 。但是代码来自他的要点。 // DataManager.h #import #import extern N
如何在 Swift 中使用 UndoManager(以前的 NSUndoManager)? 这是我尝试复制的 Objective-C 示例: [[undoManager prepareWithInvo
我正在尝试在类似绘画的程序中设置UndoManager,但不幸失败了。我一直在查看的示例程序是文本编辑器 ( Example ),它们调用 JTextComponent 类的 addUndoableE
我尝试使用 undomanager 撤消/重做编辑顶点。 图形对象经过测试。但我不知道该怎么做编辑顶点撤消/重做。 顶点是否可以撤消/重做? 我找了很多例子都没有找到答案。 我是韩国初学者程序员。帮帮
使用 Swift 3.02 (Xcode 8.2) 我引用了答案中描述的撤消解决方案:https://stackoverflow.com/a/31450475/7448394 . 在下面的代码中,我使
我只是试图让用户在我的应用程序中执行的操作撤消。默认情况下,用户所做的任何文本编辑都具有撤消的好处,但以其他方式(通过我的代码)完成的任何操作都没有。 我可以看到文档解释说我需要获取 NSUndoMa
为什么@Environment UndoManager不更新其 canUndo当它的堆栈中有 Action 时的属性?我有一个 View ,它有一个可以使用取消/重做功能的 child ,但由于某种原
我是一名优秀的程序员,十分优秀!