¿Por qué la window principal de tipo doble es opcional?

¿Al acceder a UIapplication's window principal UIapplication's se devuelve como una UIWindow??

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

¿Por qué está volviendo como un doble opcional y qué significa y si se pone en un if let debe agregar uno ! ¿después de?

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

¿Mi primera vez fue para replace ? con un ! después del delegado pero esa no fue la solución.

@matt tiene los detalles, pero hay una solución (algo horrible, algo increíble). (Ver editar a continuación, sin embargo)

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

Dejaré la comprensión de esta línea de código como un ejercicio para el lector.

OK, miento, vamos a romperlo.

 app.delegate?.window 

Bien, hasta ahora todo bien. En este punto tenemos la UIWindow?? eso nos está dando un dolor de cabeza (y creo que es un error en la desconnection Swift entre Swift y Cocoa). Queremos queuepsarlo dos veces. Podemos hacer eso con un encadenamiento opcional ( ?. ), Pero eso lo desenvuelve y lo vuelve a enrollar, así que estamos de vuelta de donde empezamos. Sin embargo, puedes doblar la cadena opcional con ??. que es extraño, pero funciona.

Eso es genial, pero ?? no es un operador de sufijo legal. Tienes que encadenar algo. Bueno, queremos encadenar a sí mismo (es decir, "identidad"). El protocolo NSObject nos proporciona un método de identidad: self .

self es un método en NSObject , pero también es una palabra reservada en Swift, por lo que la syntax para él es `self`()

Y así tenemos nuestra locura arriba. Hazlo como quieras.

Tenga en count que desde ??. funciona, técnicamente no necesita esto. ¿Puedes aceptar que la view es UIWindow?? y uso ??. en ella como view??.frame . Es un poco ruidoso, pero probablemente no crea problemas reales para los pocos lugares que deberían ser necesarios.

(*) Solía ​​pensar en esto como un error en Swift, pero no se puede corregir directamente mediante el encadenamiento opcional. El problema es que no hay una window pasada de encadenamiento opcional. Entonces no estoy seguro de dónde está el lugar correcto para solucionarlo. ¿Swift podría permitir un postfix- ? para significar "aplanar" sin necesidad de encadenar, pero eso se siente extraño. Supongo que el operador correcto sería interrobang delegate?.window‽ : D Estoy seguro de que no causaría ninguna confusión.

EDITAR:

Joseph Lord señaló la mejor solución (que es muy similar a las técnicas que he estado usando para evitar trivial if-let, pero no había pensado de esta manera antes):

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

Estoy de acuerdo con él en que esta es la respuesta correcta.

Es porque la propiedad de la window está en duda (es opcional). Por lo tanto, necesita un signo de interrogación porque podría o no existir una propiedad de window y otro signo de interrogación porque el valor de retorno de esa propiedad de window es en sí mismo un Opcional. Así obtenemos un Opcional de doble envoltura (como explico en mi tutorial : desplácese hacia abajo hasta el cuadro Sugerencia donde hablo de lo que sucede cuando una propiedad opcional tiene un valor Opcional).

Por lo tanto, una manera de express esto sería en dos etapas: una para emitir (y desenvolver ese Opcional), y otra para search la window (y desenvolverla Opcional):

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

Ahora view es una UIWindow.

Por supuesto, si está seguro de su terreno (que probablemente sea), puede forzar el yeso en la primera línea y el desenvolvimiento en la segunda línea. Entonces, en Swift 1.2:

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

¡Oh, el doble opcional! A veces puedes usar un double-bang (dos signos de exclamación), pero no puedes lanzar de esa manera con un enlace opcional. Entonces … mi remezcla de todo el otro código te da un object UIWindow llamado window del tipo no opcional:

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

Pero no perdamos time y solo usemos

 let window = UIApplication.shanetworking.delegate!.window!! 

y listo

Con el advenimiento de Swift2 para mí, una solución habitual en este tipo de casos es

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