Dou*_*iot 5 cocoa objective-c nsdocument appkit swift
在我的应用程序中,一个NSDocument子类关键任务硬件 - 用户真的不想意外关闭文档!所以,我已经实现canCloseDocumentWithDelegate…了NSAlert在关闭之前显示和询问。
我现在试图在用 Swift 编写的应用程序中实现同样的事情。
由于答案是异步出现的,“应该关闭”结果将传递给委托的回调,而不是简单地返回。在 的文档中-canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo:,它说:
shouldCloseSelector 回调方法应具有以下签名:
- (void)document:(NSDocument *)doc shouldClose:(BOOL)shouldClose contextInfo:(void *)contextInfo
所以,由于有 3 个不同类型的参数,我不能使用简单的performSelector:withObject:样式方法——你必须使用 NSInvocation。请注意,委托的类型是id,并且上面的签名没有出现在任何正式协议中——您不能简单地正常调用该方法。(有关如何执行此操作的示例,请参阅此邮件列表帖子)
现在,问题是,Swift 中不允许使用 NSInvocation!参见 Swift 博客“NSMethodSignature 发生了什么”:
将 Cocoa 框架引入 Swift 为我们提供了一个独特的机会,以全新的视角看待我们的 API。我们发现我们觉得不符合 Swift 目标的类,通常是因为我们将安全放在首位。例如,一些与动态方法调用相关的类在 Swift 中没有公开,即
NSInvocation和NSMethodSignature。
这听起来是件好事,但是当一个简单的NSDocumentAPI 仍然需要 NSInvocation时就会失败!对整个问题的真正解决方案是让 ApplecanCloseDocument…使用块回调引入新的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)
}
Run Code Online (Sandbox Code Playgroud)
如果您需要将此行为移至另一种方法(例如,在工作表获得用户确认后),只需将委托和 shouldCloseSelector 存储在属性中,以便您稍后访问它们。
| 归档时间: |
|
| 查看次数: |
927 次 |
| 最近记录: |