为什么类型的主窗口是双选的?

时间:2015-03-06 15:22:01

标签: ios swift optional uiwindow

访问UIapplication's主窗口时,会以UIWindow??

的形式返回
let view = UIApplication.sharedApplication().delegate?.window // view:UIWindow??

为什么它作为双重可选项返回,它是什么意思,如果放入if let,我应该在其后添加一个!吗?

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

我的第一个问题是在委托之后用?替换!,但这不是解决方案。

4 个答案:

答案 0 :(得分:27)

@matt有详细信息,但有一个(有点可怕,有点可怕)的解决方法。 (参见下面的编辑)

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

我会将对这一行代码的理解留作读者的练习。

好吧,我撒谎,让我们把它分解。

app.delegate?.window
好的,到目前为止一切顺利。在这一点上,我们有UIWindow??让我们头痛(我相信Swift 中的错误在Swift和Cocoa之间断开连接)。我们想要崩溃两次。我们可以使用可选链接(?.)来做到这一点,但是这会解开并重新打包,所以我们回到了我们开始的地方。但是,您可以使用??.双重可选链,这是奇怪的,但有效。

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

selfNSObject上的方法,但它也是Swift中的保留字,因此其语法为`self`()

所以我们疯狂了。照你的意愿去做。

请注意,由于??.有效,因此从技术上讲,您不需要这样做。您可以接受viewUIWindow??并在其上使用??.,例如view??.frame。它有点吵,但可能不会为它应该需要的几个地方带来任何实际问题。

(*)我曾经认为这是Swift中的一个错误,但它不能通过可选链接直接修复。问题是没有可选的链接window。所以我不确定在哪里找到合适的地方。 Swift可以允许后缀 - ?表示“变平”而不需要链接,但这感觉很奇怪。我想合适的操作员将是interrobang delegate?.window‽:D我相信这不会造成任何混淆。

编辑:

Joseph Lord pointed out the better solution(这与我为避免琐碎的if-let而使用的技术非常相似,但之前没有考虑过这种方式):

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

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

答案 1 :(得分:17)

这是因为window属性本身存在疑问(它是可选的)。因此,您需要一个问号因为可能存在或不存在窗口属性,而另一个问号是因为该窗口属性的返回值本身是可选的。因此,我们得到一个双包装的Optional(正如我在我的tutorial中解释的那样:向下滚动到Tip框,我在那里讨论当可选属性具有Optional值时会发生什么)。

因此,表达这一点的一种方法将分为两个阶段 - 一个用于转换(和解包那个可选),另一个用于获取窗口(并解开 可选):

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!

答案 2 :(得分:1)

哦双重可选!有时您可以使用双重爆炸(两个感叹号),但不能使用可选绑定进行强制转换。所以......我对所有其他代码的混音会得到一个名为window的非可选类型的UIWindow对象:

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

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

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

完成。

答案 3 :(得分:0)

随着Swift2的出现,我在这种情况下的常用解决方法是

ERROR: Unexpected HTTP Status code: 404 Not Found (url = http://localhost:54321/99/Models.bin/DeepLearning_model_R_1449814346828_5?dir=D%3A%2FGoogle%20Drive%2FMio%2FKaggle%2FDigital%20Challenge%2Fmodels%2FDeepLearning_model_R_1449814346828_5&force=FALSE)

water.exceptions.H2OKeyNotFoundArgumentException
 [1] "water.api.ModelsHandler.getFromDKV(ModelsHandler.java:126)"                           
 [2] "water.api.ModelsHandler.exportModel(ModelsHandler.java:222)"                          
 [3] "sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)"                          
 [4] "sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)"        
 [5] "sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)"
 [6] "java.lang.reflect.Method.invoke(Method.java:497)"                                     
 [7] "water.api.Handler.handle(Handler.java:64)"                                            
 [8] "water.api.RequestServer.handle(RequestServer.java:644)"                               
 [9] "water.api.RequestServer.serve(RequestServer.java:585)"                                
[10] "water.JettyHTTPD$H2oDefaultServlet.doGeneric(JettyHTTPD.java:617)"                    
[11] "water.JettyHTTPD$H2oDefaultServlet.doGet(JettyHTTPD.java:559)"                        
[12] "javax.servlet.http.HttpServlet.service(HttpServlet.java:735)"                         
[13] "javax.servlet.http.HttpServlet.service(HttpServlet.java:848)"                         
[14] "org.eclipse

.jetty.servlet.ServletHolder.handle(ServletHolder.java:684)"               

Error in .h2o.doSafeREST(h2oRestApiVersion = h2oRestApiVersion, urlSuffix = page,  : 
  Object 'DeepLearning_model_R_1449814346828_5' not found for argument: model_id