在我的应用程序中,NSDocument
子类关键任务硬件 - 用户真的不想意外关闭文档!所以,我已经实现了canCloseDocumentWithDelegate…
显示一个NSAlert
并在关门前询问。
我现在正在尝试在用 Swift 编写的应用程序中实现同样的事情。
由于答案是异步出现的,因此“应该关闭”结果将传递给委托上的回调,而不是简单地返回。在文档中-canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo:
, 它说:
shouldCloseSelector 回调方法应具有以下签名:
- (void)document:(NSDocument *)doc shouldClose:(BOOL)shouldClose contextInfo:(void *)contextInfo
因此,由于有 3 个不同类型的参数,我不能使用简单的performSelector:withObject:
样式方法——你必须使用 NSInitation。请注意,委托的类型是id
,并且上面的签名不会出现在任何正式协议中——你不能简单地正常调用该方法。 (看这个邮件列表帖子例如应该如何完成此操作)
现在的问题是,Swift 中不允许 NSInitation!请参阅 Swift 博客“NSMethodSignature 发生了什么”:
将 Cocoa 框架引入 Swift 为我们提供了一个独特的机会,以全新的视角审视我们的 API。我们发现一些类与 Swift 的目标不符,通常是因为我们优先考虑安全性。例如,一些与动态方法调用相关的类在 Swift 中并未公开,即NSInvocation
and NSMethodSignature
.
这听起来像是一件好事,但当一个简单的事情发生时就会失败NSDocument
API 仍然需要 NSInitation!整个问题的真正解决方案是苹果推出新的canCloseDocument…
使用块回调的 API。但在那之前,最好的解决方案是什么?
您可以使用一些低级运行时函数来解决此问题:
override func canCloseDocumentWithDelegate(delegate: AnyObject, shouldCloseSelector: Selector, contextInfo: UnsafeMutablePointer<Void>) {
let allowed = true // ...or false. Add your logic here.
let Class: AnyClass = object_getClass(delegate)
let method = class_getMethodImplementation(Class, shouldCloseSelector)
typealias signature = @convention(c) (AnyObject, Selector, AnyObject, Bool, UnsafeMutablePointer<Void>) -> Void
let function = unsafeBitCast(method, signature.self)
function(delegate, shouldCloseSelector, self, allowed, contextInfo)
}
如果您需要将此行为移至另一个方法(例如,在工作表获得用户确认后),只需将委托和 shouldCloseSelector 存储在属性中,以便稍后访问它们。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)