2016-12-19 42 views
3

在我们的应用中,我们使用下面的代码:NSUndoManager斯威夫特代码铸造NSUndoManagerProxy崩溃

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

这编译没有警告和运行MacOS的10.12塞拉利昂下的罚款。然而它在运行时崩溃在10.9 - 10.11(小牛队直到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中的行为显然发生了变化。我在Swift 3和SDK 10.12上使用Xcode 8.2

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

任何人都遇到同样的问题?更重要的是:任何人想出一条出路?

回答

2

我非常惊讶,我听到你的第一个代码在macOS 10.12上工作。方法prepare(withInvocationTarget:)已经是这个几乎不适用于Swift的东西。不仅返回的代理对象不是原始类的实例,也不是该对象不是NSObject的后代(在某些以前的OS X中是租赁的)。

无论如何,这是一两件事值得一试:

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

我也惊讶,铸造AnyObject编译:-)。在AnyObject上调用的未知方法期望编译器警告。但我可以确认你的解决方案的作品! – Marius

+0

我可以证实这个解决方案也适用于我(虽然我想知道为什么错误出现在第一位),但我想补充一点,我还需要声明'MyObjectType'为'NSObject'。声明只是'class MyObjectType {...}'会导致编译错误'类型'AnyObject'的值没有成员'myMethod'“。 – HuaTham