为什么 double 类型的 main window 是可选的?
Why is main window of type double optional?
当访问 UIapplication's
main window 时,它作为 UIWindow??
返回
let view = UIApplication.sharedApplication().delegate?.window // view:UIWindow??
为什么它作为双精度返回,它是什么意思,如果放入 if let
我应该在它后面添加一个 !
吗?
if let view = UIApplication.sharedApplication().delegate?.window!
我的第一个想法是在委托后用 !
替换 ?
,但这不是解决方案。
因为window
属性本身有疑问(可选)。因此,您需要一个问号,因为可能有也可能没有 window 属性,而另一个问号是因为 window 属性 的 return 值本身是可选的。因此我们得到了一个双重包装的 Optional(正如我在 tutorial 中解释的那样:向下滚动到提示框,我在其中讨论当一个可选的 属性 具有一个 Optional 值时会发生什么)。
因此,表达这一点的一种方式是分为两个阶段——一个是转换(并展开 that 可选),另一个是获取 window(和展开 that 可选):
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!
@matt 有详细信息,但有一个(有点可怕,有点棒)解决方法。 (不过请参阅下面的编辑)
let window = app.delegate?.window??.`self`()
我将把对这行代码的理解留作reader的练习。
好吧,我说谎,我们分解一下。
app.delegate?.window
好的,到目前为止一切顺利。在这一点上,我们遇到了让我们头疼的 UIWindow??
(我相信是 Swift 中的一个 错误 Swift 和 Cocoa).我们想折叠它两次。我们可以使用可选链接 (?.
) 来做到这一点,但它会展开和重新包装,所以我们回到了起点。但是,您可以使用 ??.
双可选链,这很奇怪,但是有效。
很好,但是 ??
不是合法的后缀运算符。您实际上必须链接到某些东西。好吧,我们想链接回它自己(即 "identity")。 NSObject
协议给了我们一个标识方法:self
.
self
是 NSObject
上的方法,但它也是 Swift 中的保留字,所以它的语法是 `self`()
所以我们得到了我们的疯狂。随心所欲地使用它。
请注意,由于 ??.
有效,因此从技术上讲您不需要它。您可以只接受 view
是 UIWindow??
并像 view??.frame
一样在其上使用 ??.
。它有点吵,但可能不会对少数需要它的地方造成任何实际问题。
(*) 我曾经认为这是 Swift 中的错误,但它不能通过可选链接直接修复。问题是没有可选的链接过去 window
。所以我不确定修复它的正确位置在哪里。 Swift 可以允许后缀-?
表示 "flatten" 而无需链接,但这感觉很奇怪。我想正确的运算符应该是 interrobang delegate?.window‽
:D 我相信这不会引起任何混淆。
编辑:
Joseph Lord pointed out the better solution(这与我一直用来避免琐碎的 if-let 的技术非常相似,但之前没有想到过这种方式):
let window = app.delegate?.window ?? nil // UIWindow?
我同意他的看法,这是正确的答案。
对于我来说,随着 Swift2 的出现,在这种情况下通常的解决方法是
if let _window = UIApplication.sharedApplication().delegate?.window, window = _window {
// Some code... i.e.
let frame = window.frame
}
双选哦!有时您可以使用 double-bang(两个感叹号),但您不能使用可选绑定那样进行转换。所以...我对所有其他代码的混音为您提供了一个名为 window
的 non-optional 类型的 UIWindow 对象:
guard let w = UIApplication.shared.delegate?.window, let window = w else { return }
但我们不要浪费时间,直接使用
let window = UIApplication.shared.delegate!.window!!
完成。
当访问 UIapplication's
main window 时,它作为 UIWindow??
let view = UIApplication.sharedApplication().delegate?.window // view:UIWindow??
为什么它作为双精度返回,它是什么意思,如果放入 if let
我应该在它后面添加一个 !
吗?
if let view = UIApplication.sharedApplication().delegate?.window!
我的第一个想法是在委托后用 !
替换 ?
,但这不是解决方案。
因为window
属性本身有疑问(可选)。因此,您需要一个问号,因为可能有也可能没有 window 属性,而另一个问号是因为 window 属性 的 return 值本身是可选的。因此我们得到了一个双重包装的 Optional(正如我在 tutorial 中解释的那样:向下滚动到提示框,我在其中讨论当一个可选的 属性 具有一个 Optional 值时会发生什么)。
因此,表达这一点的一种方式是分为两个阶段——一个是转换(并展开 that 可选),另一个是获取 window(和展开 that 可选):
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!
@matt 有详细信息,但有一个(有点可怕,有点棒)解决方法。 (不过请参阅下面的编辑)
let window = app.delegate?.window??.`self`()
我将把对这行代码的理解留作reader的练习。
好吧,我说谎,我们分解一下。
app.delegate?.window
好的,到目前为止一切顺利。在这一点上,我们遇到了让我们头疼的 UIWindow??
(我相信是 Swift 中的一个 错误 Swift 和 Cocoa).我们想折叠它两次。我们可以使用可选链接 (?.
) 来做到这一点,但它会展开和重新包装,所以我们回到了起点。但是,您可以使用 ??.
双可选链,这很奇怪,但是有效。
很好,但是 ??
不是合法的后缀运算符。您实际上必须链接到某些东西。好吧,我们想链接回它自己(即 "identity")。 NSObject
协议给了我们一个标识方法:self
.
self
是 NSObject
上的方法,但它也是 Swift 中的保留字,所以它的语法是 `self`()
所以我们得到了我们的疯狂。随心所欲地使用它。
请注意,由于 ??.
有效,因此从技术上讲您不需要它。您可以只接受 view
是 UIWindow??
并像 view??.frame
一样在其上使用 ??.
。它有点吵,但可能不会对少数需要它的地方造成任何实际问题。
(*) 我曾经认为这是 Swift 中的错误,但它不能通过可选链接直接修复。问题是没有可选的链接过去 window
。所以我不确定修复它的正确位置在哪里。 Swift 可以允许后缀-?
表示 "flatten" 而无需链接,但这感觉很奇怪。我想正确的运算符应该是 interrobang delegate?.window‽
:D 我相信这不会引起任何混淆。
编辑:
Joseph Lord pointed out the better solution(这与我一直用来避免琐碎的 if-let 的技术非常相似,但之前没有想到过这种方式):
let window = app.delegate?.window ?? nil // UIWindow?
我同意他的看法,这是正确的答案。
对于我来说,随着 Swift2 的出现,在这种情况下通常的解决方法是
if let _window = UIApplication.sharedApplication().delegate?.window, window = _window {
// Some code... i.e.
let frame = window.frame
}
双选哦!有时您可以使用 double-bang(两个感叹号),但您不能使用可选绑定那样进行转换。所以...我对所有其他代码的混音为您提供了一个名为 window
的 non-optional 类型的 UIWindow 对象:
guard let w = UIApplication.shared.delegate?.window, let window = w else { return }
但我们不要浪费时间,直接使用
let window = UIApplication.shared.delegate!.window!!
完成。