为什么主窗口的types是double可选的?

当访问UIapplication's主窗口时,它将作为UIWindow??返回UIWindow??

 let view = UIApplication.sharedApplication().delegate?.window // view:UIWindow?? 

为什么它返回作为一个双选项,它是什么意思,如果放入一个if let我应该加一个! 之后呢?

 if let view = UIApplication.sharedApplication().delegate?.window! 

我的第一个虽然是取代?! 委托后,但这不是解决scheme。

@matt有细节,但有一个(有点可怕,有点令人敬畏)的解决方法。 (尽pipe如下编辑)

 let window = app.delegate?.window??.`self`() 

我将把这行代码的理解作为读者的一个练习。

好吧,我说谎,让我们分手吧。

 app.delegate?.window 

好,那么好。 在这一点上我们有UIWindow?? 这让我们头疼(我相信是Swift和Cocoa之间的Swift断开连接的一个错误 )。 我们想要折叠两次。 我们可以用可选的链接( ?. )来做到这一点,但是解开和重新包装,所以我们回到了我们开始的地方。 你可以用双重可选链,但是,用??. 这是奇怪的,但工程。

这很好,但?? 不是一个合法的后缀操作符。 你必须实际上链接到一些东西。 那么,我们想链接回自己(即“身份”)。 NSObject协议为我们提供了一种身份识别方法: self

selfNSObject一个方法,但它也是Swift中的一个保留字,所以它的语法是`self`()

所以我们得到我们的疯狂以上。 按照你的意愿去做。

请注意,自??.以来??. 工作,你不技术上需要这个。 你可以接受的viewUIWindow?? 并使用??. 就像这个view??.frame一样。 这有点吵,但可能不会造成任何真正的问题,应该需要的less数地方。

(*)我曾经认为这是Swift中的一个bug,但是它不能直接通过可选的链接来修复。 问题是没有可选的链接过去的window 。 所以我不确定在哪里解决这个问题。 Swift可以允许postfix- ? 意思是“扁平化”而不需要链接,但这种感觉很奇怪。 我想正确的运营商将interrobang delegate?.window‽ :D我相信这不会造成任何混淆。

编辑:

Joseph Lord指出了更好的解决scheme (这与我一直使用的避免微不足道的技术非常相似,但之前没有这样想过):

 let window = app.delegate?.window ?? nil // UIWindow? 

我同意他的看法,这是正确的答案。

这是因为window属性本身是有疑问的(这是可选的)。 因此,您需要一个问号,因为有可能是或者可能不是一个窗口属性,而另一个问号是因为该窗口属性的返回值本身是一个可选项。 因此,我们得到一个双重包装可选(正如我在我的教程中解释:向下滚动到提示框,在那里我会谈论什么时候可选的属性有一个可选的值)。

因此,expression这一点的一种方法将分为两个阶段 – 一个投射(并解开可选)和一个获取窗口(并解开可选):

 if let del = UIApplication.sharedApplication().delegate as? AppDelegate { if let view = del.window { 

现在view是一个UIWindow。

当然,如果你确定了你的理由(你可能是这样),你可以在第一行强制转换,在第二行中解开。 所以,在Swift 1.2中:

 let del = UIApplication.sharedApplication().delegate as! AppDelegate let view = del.window! 

哦,双选! 有时候你可以使用双重感叹号(两个感叹号),但是你不能用可选的绑定方式进行强制转换。 所以…我的所有其他代码的混音得到一个UIWindow对象称为window的非可选类:

 guard let w = UIApplication.shared.delegate?.window, let window = w else { return } 

但是,我们不要浪费时间,只是使用

 let window = UIApplication.shared.delegate!.window!! 

并做好。

随着Swift2的到来,在这种情况下通常的解决方法是

 if let _window = UIApplication.sharedApplication().delegate?.window, window = _window { // Some code... ie let frame = window.frame }