swift swift3 optional string-interpolation

swift - Cómo resolver “La interpolación de cadenas produce una descripción de depuración para un valor opcional; ¿querías hacer esto explícito? ”en Xcode 8.3 beta?



swift3 optional (6)

Desde la versión beta 8.3, billones de advertencias "La interpolación de cadenas produce una descripción de depuración para un valor opcional; ¿quiso hacer esto explícito?" apareció en mi código.

Por ejemplo, la advertencia apareció en la siguiente situación, donde las opciones podrían llevar a cero:

let msg = "*** Error /(options["taskDescription"]): cannot load /(sUrl) /(error)"

Como se diseñó anteriormente, estaba bien para mí (y para el compilador) que los opcionales se interpolaran como ''nulo''. Pero el compilador cambió de opinión.

Lo que sugiere el compilador es agregar un constructor de cadenas con la siguiente descripción:

let msg = "*** Error /(String(describing: options["taskDescription"])): cannot load /(sUrl) /(error)"

Obviamente, los resultados son explícitos pero también muy engorrosos en mi opinión. ¿Hay alguna opción mejor? ¿Tengo que arreglar todas esas advertencias o mejor esperar la próxima beta?


Después de actualizar a Xcode 8.3 y recibir muchos mensajes de advertencia, se me ocurrió lo siguiente que se parece más al comportamiento de salida original, fácil de agregar, reduce la verbosidad del uso de "Cadena (que describe :)" tanto en el código como en la salida .

Básicamente, agregue una extensión Opcional que proporcione una Cadena que describa la cosa en el opcional, o simplemente "nulo" si no está configurado. Además, si la cosa en el opcional es una Cadena, póngala entre comillas.

extension Optional { var orNil : String { if self == nil { return "nil" } if "/(Wrapped.self)" == "String" { return "/"/(self!)/"" } return "/(self!)" } }

Y uso en un patio de recreo:

var s : String? var i : Int? var d : Double? var mixed = "s = /(s.orNil) i = /(i.orNil) d = /(d.orNil)" // "s = nil i = nil d = nil" d = 3 i = 5 s = "" mixed = "s = /(s.orNil) i = /(i.orNil) d = /(d.orNil)" // "s = "" i = 5 d = 3.0" s = "Test" d = nil mixed = "s = /(s.orNil) i = /(i.orNil) d = /(d.orNil)" // "s = "Test" i = 5 d = nil"

Gracias por la ayuda del siguiente enlace:

check-if-variable-is-an-optional-and-what-type-it-wraps


Dos formas más fáciles de lidiar con este problema.

Opción 1:

El primero sería "desenvolviendo a la fuerza" el valor que le gustaría devolver usando una explosión (!)

var someValue: Int? = 5 print(someValue!)

Salida:

5

Opcion 2:

La otra forma, que podría ser la mejor manera, es "desenvolver de forma segura" el valor que desea devolver.

var someValue: Int? = 5 if let newValue = someValue { print(newValue) }

Salida:

5

Recomendaría ir con la opción 2.

Consejo: Evite el desenvolvimiento forzado (!) Siempre que sea posible, ya que no estamos seguros si siempre tendremos el valor para desenvolver.


Este es un cambio que se realizó en esta solicitud de extracción debido al hecho de que la interpolación de Optional(...) en la cadena resultante a menudo no es deseable, y puede ser especialmente sorprendente en casos con opciones implícitamente desenvueltas . Puede ver la discusión completa de este cambio en la lista de correo here .

Como se mencionó en la discusión de solicitud de extracción (aunque desafortunadamente no es por Xcode), una forma un poco mejor de silenciar la advertencia que el uso de String(describing:) es agregar un reparto al tipo opcional de lo que sea que esté interpolando, por lo que ejemplo:

var i: Int? = 5 var d: Double? = nil print("description of i: /(i as Int?)") // description of i: Optional(5) print("description of d: /(d as Double?)") // description of d: nil

Que también se puede generalizar as Optional :

print("description of i: /(i as Optional)") // description of i: Optional(5) print("description of d: /(d as Optional)") // description of d: nil

En Swift 5, con el nuevo sistema de interpolación de cadenas introducido por SE-0228 , otra opción es agregar una sobrecarga de appendInterpolation personalizada para appendInterpolation :

extension DefaultStringInterpolation { mutating func appendInterpolation<T>(optional: T?) { appendInterpolation(String(describing: optional)) } } var i: Int? = 5 var d: Double? = nil print("description of i: /(optional: i)") // description of i: Optional(5) print("description of d: /(optional: d)") // description of d: nil

Y, si lo desea, incluso puede eliminar la etiqueta del argumento para deshabilitar la advertencia por completo dentro de un módulo (o dentro de un archivo en particular si lo marca como fileprivate ):

extension DefaultStringInterpolation { mutating func appendInterpolation<T>(_ optional: T?) { appendInterpolation(String(describing: optional)) } } var i: Int? = 5 var d: Double? = nil print("description of i: /(i)") // description of i: Optional(5) print("description of d: /(d)") // description of d: nil

Aunque personalmente preferiría mantener la etiqueta del argumento.


Haga doble clic en el triángulo amarillo que se muestra en la línea que contiene esta advertencia. Esto mostrará FixIt con dos soluciones.

  1. Use String(describing:) para silenciar esta advertencia:

    Usando esto se convertirá en String(describing:<Variable>)

    P.ej. : String(describing: employeeName)

  2. Proporcione un default value para evitar esta advertencia:

    Usar esto se convertirá en (<Variable> ?? default value)

    Por ejemplo: employeeName ?? “Anonymous” as! String employeeName ?? “Anonymous” as! String


Parece que usar String (que describe: opcional) es lo más simple.

valor por defecto ?? no tiene sentido para no cadenas, por ejemplo, Int.
Si Int es nulo, entonces desea que el registro muestre ''nil'' no predeterminado a otro Int, por ejemplo 0.

Algunos códigos de juegos para probar:

var optionalString : String? = nil var optionalInt : Int? = nil var description_ = "" description_ = description_ + "optionalString: /(String(describing: optionalString))/r" description_ = description_ + " optionalInt: /(String(describing: optionalInt))/r" print(description_)

Salida

optionalString: nil optionalInt: nil


Ver la solución de Ole Begeman para esto . Me encanta. Se crea un ??? operador que puede usar así:

var someValue: Int? = 5 print("The value is /(someValue ??? "unknown")") // → "The value is 5" someValue = nil print("The value is /(someValue ??? "unknown")") // → "The value is unknown"