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:
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.
-
Use
String(describing:)
para silenciar esta advertencia:Usando esto se convertirá en
String(describing:<Variable>)
P.ej. :
String(describing: employeeName)
-
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"