NSUndoManager在Swift代码

时间:2016-12-19 10:41:54

标签: swift macos nsundomanager

在我们的应用程序中,我们使用以下代码:

let lInvocationTarget = lUndoManager.prepare(withInvocationTarget: self)
let _ = (lInvocationTarget as! MyObjectType).myMethod(_: self.opacity, undoManager: lUndoManager)

这编译没有警告,并在macOS 10.12 Sierra下正常运行。然而它在10.9 - 10.11(Mavericks直到El Capitan)的运行时崩溃了。 崩溃报告通知:

  

无法将“NSUndoManagerProxy”类型的值(0x7fff76d6d9e8)转换为“MyObjectType”(0x108b82218)。

然后我将代码改写为:

if let lInvocationTarget = lUndoManager.prepare(withInvocationTarget: self) as? MyObjectType {
    let _ = lInvocationTarget.setOpacity(_: self.opacity, undoManager: lUndoManager)
}

然后它不会崩溃,但是撤消根本不起作用。 最后一种写法直接来自Apples documentation,因此在Swift 3或10.12 SDK中显然改变了行为。我正在使用Xcode 8.2和Swift 3以及SDK 10.12

registerUndo(withTarget,selector:,object :)不合适,因为我有很多其他可撤销方法和更多参数。真的不想把那些包在字典中的orso。即使选择器现在非常安全,我仍然不喜欢它们。 还有基于块的API(registerUndo(withTarget:handler :)),但不幸的是只有10.11 +。

有人遇到过同样的问题吗?更重要的是:有人想出办法吗?

2 个答案:

答案 0 :(得分:3)

我非常惊讶于我在macOS 10.12上听到您的第一个代码正常工作。方法prepare(withInvocationTarget:)一直是这个 - 难以在Swift中工作的东西。不仅返回的代理对象不是原始类的实例,而且对象也不是NSObject的后代(在某些以前的OS X中至少是这样)。

无论如何,这是值得一试的事情:

let lInvocationTarget = lUndoManager.prepare(withInvocationTarget: self)
_ = (lInvocationTarget as AnyObject).myMethod(self.opacity, undoManager: lUndoManager)

答案 1 :(得分:0)

我发现 registerUndoWithTarget:handler:现在是一个更好的API。