为什么主窗口的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
。
self
是NSObject
一个方法,但它也是Swift中的一个保留字,所以它的语法是`self`()
所以我们得到我们的疯狂以上。 按照你的意愿去做。
请注意,自??.
以来??.
工作,你不技术上需要这个。 你可以接受的view
是UIWindow??
并使用??.
就像这个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 }