switch array swift string swift3 string-interpolation

array - Swift 3 interpolación de cadenas incorrecta con opciones implícitas sin envolver



switch en swift 3 (1)

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

Las declaraciones aún se pueden anotar como opciones T! implícitamente sin envolver T! , pero al hacerlo solo agrega un atributo oculto para informar al compilador que su valor puede ser forzado a desenvolverse en contextos que demandan su tipo T sin envolver; su tipo real es ahora T? .

Entonces puedes pensar en esta declaración:

var str: String!

como realmente se ve así:

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

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

// `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 en los que str puede verificarse como una opción fuerte, será:

// `x` is inferred to be a `String?` (because we really are assigning a `String?`) let x = str let y: Any = str // `str` is implicitly coerced from `String?` to `Any` print(str) // Same as the previous example, as `print` takes an `Any` parameter.

Y el compilador siempre preferirá tratarlo como tal sobre el desenvolvimiento forzado.

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

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

Cuando se trata de la interpolación de cadenas, debajo del capó el compilador 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<T>(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 forma predeterminada, eso es lo que el compilador deducirá que es el marcador de posición genérico T Por lo tanto, el valor de str no se str a la fuerza, y terminarás viendo la descripción de una opción.

Si desea que un IUO se desenvuelva a la fuerza cuando se usa en la interpolación de cuerdas, ¡simplemente puede usar el operador de desenrollado forzado ! :

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

o puede forzar a su tipo no opcional (en este caso, String ) para forzar al compilador a forzar implícitamente a desenvolverlo para usted:

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

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

¿Por qué los opcionales implícitamente sin envolver no se desenvuelven cuando se usa 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 la interpolación de cadenas prácticamente en todas partes en mi aplicación, que ahora ya no funciona debido a esto (¿error?).

¿Es esto incluso un error o cambiaron intencionalmente este comportamiento con Swift 3?