如何实现NSDocument方法-canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo:in Swift? [英] How can you implement the NSDocument method -canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo: in Swift?

查看:234
本文介绍了如何实现NSDocument方法-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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆