双重问号,它是如何工作的?
我正在学Swift,作为这个过程的一部分,试图弄清楚这里究竟发生了什么。 我有一个自定义的segue,我想放置我的模态视图控制器解散过渡。 曾经在objective-c中的是:
UIViewController *sourceViewController = self.sourceViewController; [sourceViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
self
是UIStoryboardSegue
一个实例。 我在Swift中翻译了这个片段:
self.sourceViewController.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
从编译器得到这个错误:
“的UIViewController? 没有名为“dismissViewControllerAnimated”的成员
现在, 通过文档 , presentingViewController
方法如下所示:
var presentingViewController: UIViewController? { get }
从我所了解的Swift语言文档中, ?
如果有的话,应该解开价值。 在这种情况下,视图控制器。 不明原因的事实是:如果我把一个双重的问号,它编译和工作:
self.sourceViewController.presentingViewController??.dismissViewControllerAnimated(true, completion: nil)
有人能告诉我我失踪了吗? 那该怎么办?
额外的?
需要是由于sourceViewController
返回一个AnyObject
而不是一个UIViewController
。 这是Objective-C的API转换中的一个缺陷(其中这种属性返回一个相当无意义的id
)。 从iOS 8 beta 5开始,这仍然是一个持续的过程,显然这些API还没有被修复。
如果您提供适当的演员,它将按预期工作
(self.sourceViewController as UIViewController).presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
现在,为什么我们需要额外的?
什么时候处理AnyObject
?
AnyObject
可以表示任何对象types,就像Objective-C
id
一样。 所以在编译时你可以调用任何现有的方法,例如sourceViewController
。
当你这样做的时候,它会触发从AnyObject
到UIViewController
的隐式downcast,根据官方指南 :
与Swift中的所有向下转换一样,从
AnyObject
转换为更具体的对象types不保证成功,因此返回一个可选的值
所以,当你这样做
self.sourceViewController.presentingViewController??
它隐含地翻译成类似的东西
let source: UIViewController? = self.sourceViewController as? UIViewController let presenting: UIViewController? = source?.presentingViewController
这就是为什么你需要两个?
:一个用于parsingdowncast,另一个用于presentingViewController
。
最后,总是按照文档:
当然,如果您确定对象的types(并且知道它不是零),则可以使用as运算符强制调用。
这正是我上面提出的解决scheme。