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

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

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

¿Por qué está volviendo como una opción doble y qué significa y si se pone en una if let debo añadir uno ! ¿después de?

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

¿Mi primer bash fue reemplazar ? con a ! después de delegado, pero esa no era la solución.

    @matt tiene los detalles, pero hay una solución (algo horrible, algo impresionante). (Ver edición abajo, 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 descomponerlo.

     app.delegate?.window 

    OK, hasta ahora todo bien. En este punto, tenemos la UIWindow?? eso nos está dando dolor de cabeza (y creo que es un error en la desconexión de Swift entre Swift y Cocoa). Queremos colapsarlo dos veces. Podemos hacer eso con un encadenamiento opcional ( ?. ), Pero eso se desenvuelve y se vuelve a enrollar, así que estamos de vuelta desde donde comenzamos. Sin embargo, puede doble cadena opcional con ??. lo cual es extraño, pero funciona.

    Eso es genial, pero ?? no es un operador de sufijo legal Tienes que encadenarte a algo. Bueno, queremos encadenarnos a sí mismo (es decir, “identidad”). El protocolo NSObject nos da 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í conseguimos nuestra locura arriba. Hazlo como quieras.

    Tenga en cuenta que desde ??. funciona, técnicamente no necesitas esto. ¿Puedes simplemente aceptar que la view es UIWindow?? y uso ??. en él como view??.frame . Es un poco ruidoso, pero probablemente no cree ningún problema real para los pocos lugares donde debería ser necesario.

    (*) Solía ​​pensar en esto como un error en Swift, pero no se puede reparar directamente mediante el encadenamiento opcional. El problema es que no hay una window pasada de encadenamiento opcional. Así que no estoy seguro de dónde está el lugar correcto para arreglarlo. Swift podría permitir un postfix- ? para significar “aplanar” sin requerir encadenamiento, pero eso se siente extraño. Supongo que el operador correcto sería 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 puede haber o no una propiedad de ventana y otro signo de interrogación porque el valor de retorno de esa propiedad de ventana es en sí mismo un Opcional. Por lo tanto, obtenemos un Opcional de doble envoltura (como explico en mi tutorial : desplácese hacia abajo al cuadro Tip donde hablo de lo que sucede cuando una propiedad opcional tiene un valor Opcional).

    Por lo tanto, una forma de express esto sería en dos etapas: una para lanzar (y desenvolver esa Opcional), y otra para recuperar la ventana (y desenvolver esa Opcional):

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

    Ahora view es una ventana UI.

    Por supuesto, si estás seguro de tu suelo (que probablemente eres), puedes forzar el yeso en la primera línea y desenvolverlo en la segunda línea. Entonces, en Swift 1.2:

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

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

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

    Pero no perdamos el tiempo y solo usemos

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

    y estar hecho.

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

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