Swift 3 interpolación de cadena incorrecta con opciones opcionales sin envolver

¿Por qué las opciones opcionales no envueltas implícitamente no se desenvuelven cuando se utiliza la interpolación de cadenas en Swift 3?

Ejemplo : ejecutar el siguiente código en el patio de recreo

var str: String! str = "Hello" print("The following should not be printed as an optional: \(str)") 

produce esta salida:

 The following should not be printed as an optional: Optional("Hello") 

Por supuesto, puedo concatenar cadenas con el operador + pero estoy usando interpolación de cadenas prácticamente en todas partes en mi aplicación, que ahora ya no funciona debido a esto (¿error?).

¿Esto es incluso un error o cambiaron intencionalmente este comportamiento con Swift 3?

Según SE-0054 , ImplicitlyUnwrappedOptional ya no es un tipo distinto; solo hay Optional ahora.

Las declaraciones todavía se pueden anotar como opciones opcionales T! envuelto implícitamente T! , pero al hacerlo, solo agrega un atributo oculto para informar al comstackdor de que su valor puede ser forzado a desenvolverse en contextos que exigen su tipo desenvuelto T ; su tipo real es ahora T? .

Entonces puedes pensar en esta statement:

 var str: String! 

como en realidad se ve así:

 @_implicitlyUnwrapped // this attribute name is fictitious var str: String? 

Solo el comstackdor ve este atributo @_implicitlyUnwrapped , pero lo que permite es el desenvolvimiento implícito del valor de str en contextos que demandan un String (su tipo desenvuelto):

 // `str` cannot be type-checked as a strong optional, so the compiler will implicitly // force unwrap it (causing a crash in this case) let x: String = str // We're accessing a member on the unwrapped type of `str`, so it'll also be implicitly // force unwrapped here print(str.count) 

Pero en todos los demás casos donde str puede ser revisado por tipo como un fuerte opcional, será:

 // x is inferred to be a String? (because we really are assigning a String?) let x = str // str is implicitly coerced from String? to Any let y: Any = str 

Y el comstackdor siempre preferirá tratarlo como tal al desenrollar la fuerza.

Como dice la propuesta (el énfasis es mío):

Si la expresión puede verificarse explícitamente con un fuerte tipo opcional, lo será . Sin embargo, el verificador de tipos volverá a forzar el opcional si es necesario. El efecto de este comportamiento es que el resultado de cualquier expresión que se refiera a un valor declarado como T! tendrá tipo T o tipo T? .

Cuando se trata de interpolación de cadenas, bajo el capó el comstackdor usa este inicializador del protocolo _ExpressibleByStringInterpolation para evaluar un segmento de interpolación de cadenas:

 /// Creates an instance containing the appropriate representation for the /// given value. /// /// Do not call this initializer directly. It is used by the compiler for /// each string interpolation segment when you use string interpolation. For /// example: /// /// let s = "\(5) x \(2) = \(5 * 2)" /// print(s) /// // Prints "5 x 2 = 10" /// /// This initializer is called five times when processing the string literal /// in the example above; once each for the following: the integer `5`, the /// string `" x "`, the integer `2`, the string `" = "`, and the result of /// the expression `5 * 2`. /// /// - Parameter expr: The expression to represent. init(stringInterpolationSegment expr: T) 

Por lo tanto, cuando su código lo llama implícitamente:

 var str: String! str = "Hello" print("The following should not be printed as an optional: \(str)") 

¿Como el tipo real de str es String? , de manera predeterminada, eso es lo que el comstackdor deducirá del marcador de posición genérico T Por lo tanto, el valor de str no se liberará de la fuerza, y terminarás viendo la descripción de un opcional.

Si desea que una IUO se desenrolle por la fuerza cuando se utiliza en la interpolación de cuerdas, ¡simplemente puede usar el operador de desenrollado de fuerza ! :

 var str: String! str = "Hello" print("The following should not be printed as an optional: \(str!)") 

o puede obligar a su tipo no opcional (en este caso String ) para forzar al comstackdor a forzar implícitamente su desenvolvimiento por usted:

 print("The following should not be printed as an optional: \(str as String)") 

ambos, por supuesto, se bloquearán si str es nil .

    Intereting Posts