双问号,它是如何工作的? [英] Double question mark, How does it work?

查看:122
本文介绍了双问号,它是如何工作的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习Swift,并且作为整个过程的一部分,试图找出究竟发生了什么。我有一个自定义segue,我想放置我的模态视图控制器解除转换。曾经在objective-c中的内容为:

I am learning Swift and, as part of the process, trying to figure out what exactly is going on here. I have a custom segue where I want to place my modal view controller dismissing transition. What used to be in objective-c as:

UIViewController *sourceViewController = self.sourceViewController;
[sourceViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];

self 是<$ c的实例$ C> UIStoryboardSegue 。
我在Swift中将此片段翻译为:

self is an instance of UIStoryboardSegue. I translated this snippet in Swift as:

self.sourceViewController.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)

从编译器中获取此错误:

getting this error from the compiler:

'UIViewController?'没有名为
的成员'dismissViewControllerAnimated'

'UIViewController?' does not have a member named 'dismissViewControllerAnimated'

现在,通过文档 presentsViewController 方法如下所示:

Now, by documentation, the presentingViewController method looks like this:

var presentingViewController: UIViewController? { get }

根据我对Swift语言文档的理解,应解包该值,如果有的话。在这种情况下,视图控制器。无法解释的事实是:如果我提出一个双重问号,它会编译并且有效:

From what I understood by the Swift language documentation, ? should unwrap the value, if any. In this case the view controller. The unexplained fact is: if I put a double question mark, it compiles and it works:

self.sourceViewController.presentingViewController??.dismissViewControllerAnimated(true, completion: nil)

有人能告诉我我错过了什么吗?该怎么办?

Can someone tell me what I am missing? What should that do?

推荐答案

需要额外的到期 sourceViewController 返回 AnyObject 而不是 UIViewController 。这是来自Objective-C的API转换中的一个缺陷(其中这样的属性返回一个相当无意义的 id )。它仍然是一个从iOS 8 beta 5开始的持续过程,显然这些API还没有修复。

The extra ? required is due sourceViewController returning an AnyObject instead of a UIViewController. This is a flaw in the API conversion from Objective-C (in which such property returns a rather meaningless id). It's still an on-going process that started with iOS 8 beta 5, and apparently those API have not been fixed yet.

如果你提供适当的演员表,它会起作用正如预期的那样

If you provide an appropriate cast, it will work as expected

(self.sourceViewController as UIViewController).presentingViewController?.dismissViewControllerAnimated(true, completion: nil)






现在,为什么我们需要额外的处理 AnyObject

AnyObject 可以表示任何对象类型,就像 id Objective-C 中一样。所以在编译时你可以调用它上面的任何现有方法,例如 sourceViewController

AnyObject can represent any object type, pretty much as id does in Objective-C. So at compile-time you can invoke any existing method on it, for example sourceViewController.

当你这样做时,它触发从 AnyObject UIViewController 的隐式向下转换,并根据官方指南

When you do so, it triggers an implicit downcast from AnyObject to UIViewController and according to the official guide:


与Swift中的所有向下转发一样,从 AnyObject 转换为更多特定对象类型不保证成功,因此返回一个可选值

As with all downcasts in Swift, casting from AnyObject to a more specific object type is not guaranteed to succeed and therefore returns an optional value

所以当你这样做时

self.sourceViewController.presentingViewController??

它隐含地转换为类似

 let source: UIViewController? = self.sourceViewController as? UIViewController
 let presenting: UIViewController? = source?.presentingViewController

这就是为什么你需要两个:一个用于解析向下转换,一个用于 presentsViewController

and that's why you need two ?: one for resolving the downcast and one for the presentingViewController.

最后,始终根据文档:


当然,如果您确定对象的类型(并且知道它不是零),您可以强制使用as运算符进行调用。

Of course, if you are certain of the type of the object (and know that it is not nil), you can force the invocation with the as operator.

这正是我上面提出的解决方案。

which is exactly my proposed solution above.

这篇关于双问号,它是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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