双问号,它是如何工作的?
Posted
技术标签:
【中文标题】双问号,它是如何工作的?【英文标题】:Double question mark, How does it work? 【发布时间】:2014-09-22 18:15:09 【问题描述】:我正在学习 Swift,作为这个过程的一部分,我试图弄清楚这里到底发生了什么。我有一个自定义 segue,我想在其中放置我的模态视图控制器解除转换。过去在 Objective-c 中是这样的:
UIViewController *sourceViewController = self.sourceViewController;
[sourceViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
self
是UIStoryboardSegue
的一个实例。
我在 Swift 中将这个 sn-p 翻译为:
self.sourceViewController.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
从编译器得到这个错误:
'UIViewController?'没有名为的成员 'dismissViewControllerAnimated'
现在,by documentation,presentingViewController
方法如下所示:
var presentingViewController: UIViewController? get
根据我对 Swift 语言文档的理解,?
应该打开该值(如果有)。在这种情况下,视图控制器。无法解释的事实是:如果我放一个双问号,它会编译并且可以工作:
self.sourceViewController.presentingViewController??.dismissViewControllerAnimated(true, completion: nil)
谁能告诉我我错过了什么?那该怎么办?
【问题讨论】:
等待 -1 的原因。我知道这可能是一个 n00b 问题(正如我所说:我正在学习),但我认为我将其表述得很清楚,这不是一个具体案例,也不是我能找到的任何记录。sourceViewController
的声明是什么?
@GabrielePetronella 我更新了这个问题。它是 UIStoryboardSegue 的属性。
【参考方案1】:
所需的额外?
是由于sourceViewController
返回AnyObject
而不是UIViewController
。这是从 Objective-C 的 API 转换中的一个缺陷(其中此类属性返回一个相当无意义的id
)。从 ios 8 beta 5 开始,这仍然是一个持续的过程,显然这些 API 尚未修复。
如果您提供适当的演员表,它将按预期工作
(self.sourceViewController as UIViewController).presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
现在,为什么我们在处理AnyObject
时需要额外的?
?
AnyObject
可以表示任何对象类型,就像id
在Objective-C
中所做的那样。所以在编译时你可以调用任何现有的方法,例如sourceViewController
。
当你这样做时,它会触发从AnyObject
到UIViewController
的隐式向下转换,并根据official guide:
与 Swift 中的所有向下转换一样,从
AnyObject
转换为更具体的对象类型并不能保证成功,因此返回一个可选值
所以当你这样做时
self.sourceViewController.presentingViewController??
它隐含地翻译成类似的东西
let source: UIViewController? = self.sourceViewController as? UIViewController
let presenting: UIViewController? = source?.presentingViewController
这就是为什么您需要两个?
:一个用于解决向下转换,一个用于presentingViewController
。
最后,总是根据文档:
当然,如果您确定对象的类型(并且知道它不是 nil),您可以使用 as 运算符强制调用。
这正是我上面提出的解决方案。
【讨论】:
解释很清楚,但我想知道一件事:第二个?
然后在做什么?第一个返回一个 AnyObject
未包装的实例,但第二个呢?不是必须允许使用该运算符的可选类型吗?
@NicolaMiotto 我想我有一个合理的解释,看我上次的更新
非常好@Gabriele,我认为您可以节省一些时间来转换此代码,“让源:UIViewController?= self.sourceViewController as?UIViewController 让呈现:UIViewController?=源?.presentingViewController”这个,“如果让presenting = self.sourceViewController as?UIViewController ”。方便检查选项。
@GeorgeTaskos 是的,这可以做到,尽管 sn-p 仅作为解释,所以我希望尽可能明确。以上是关于双问号,它是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章
TypeScript 中的问号+冒号双问号问号+点感叹号+点
TypeScript 中的问号+冒号双问号问号+点感叹号+点