如何实现NSDocument方法-canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo:in Swift? [英] How can you implement the NSDocument method -canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo: in Swift?
问题描述
在我的应用程序中, NSDocument
子类任务关键硬件 - 用户真的不想意外关闭文档!所以,我已经实现 canCloseDocumentWithDelegate ...
以显示 NSAlert
,并在结束前询问。
In my application, a NSDocument
subclass mission-critical hardware – users really don’t want to close a document by accident! So, I’ve implemented canCloseDocumentWithDelegate…
to show an NSAlert
and ask before closing.
我现在试图在Swift中编写的应用程序中实现同样的事情。
I am now trying to implement this same thing in an application written in Swift.
由于答案是异步的,结果被传递到一个代理上的回调,而不是简单地返回。在 -canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo:
的文档中,它说:
Since the answer comes asynchronously, the "should close" result is passed to a callback on a delegate, and not simply returned. In the documentation for -canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo:
, it says:
shouldCloseSelector回调方法应该具有以下签名:
The shouldCloseSelector callback method should have the following signature:
- (void)document:(NSDocument *)doc shouldClose:(BOOL)shouldClose contextInfo: (void *)contextInfo
所以,因为有3个不同类型的参数,我不能使用简单 performSelector:withObject:
样式方法 - 您必须使用NSInvocation。注意,委托是 id
类型,并且上面的签名没有出现在任何正式协议中 - 你不能简单地调用该方法。 (请参阅此邮寄名单信息
So, as there’s 3 arguments of different types, I cannot use the simple performSelector:withObject:
style methods – you have to use NSInvocation. Note that the delegate is of type id
, and the signature above does not appear in any formal protocol – you can’t simply call the method normally. (See this mailing list post for example of how this should be done)
现在,问题是,NSInvocation在Swift中是不允许的!请参阅Swift博客NSMethodSignature发生了什么:
Now, the issue is, NSInvocation is not allowed in Swift! See Swift blog "What Happened to NSMethodSignature":
将Cocoa框架带到Swift,让我们有了一个独特的机会,从新的角度看待我们的API。我们发现我们不喜欢Swift的目标的课,最常见的是我们给予安全的优先级。例如,与动态方法调用相关的一些类不在Swift中公开,即
NSInvocation
和NSMethodSignature
。
这听起来不错,但是当一个简单的 NSDocument
API需要NSInvocation仍然!这个问题的真正解决方案是苹果使用块回调引入一个新的 canCloseDocument ...
API。
That sounds like a good thing, but falls down when a simple NSDocument
API requires NSInvocation still! The real solution to this whole problem would be for Apple to introduce a new canCloseDocument…
API using a block callback. But until that happens, what’s the best solution?
推荐答案
您可以使用一些低级运行时函数来解决这个问题:
You can solve this with some low level runtime functions:
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属性,以便以后可以访问它们。
If you need to move this behaviour to another method (eg. after a sheet gets confirmation from the user), simply store the delegate and shouldCloseSelector in properties so you can access them later.
这篇关于如何实现NSDocument方法-canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo:in Swift?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!