protocols - medium - El valor enlazado en un enlace condicional debe ser de tipo opcional
swift reference (5)
Tengo un protocolo definido:
protocol Usable {
func use()
}
y una clase que se ajusta a ese protocolo.
class Thing: Usable {
func use () {
println ("you use the thing")
}
}
Me gustaría probar mediante programación si la clase Thing cumple con el protocolo utilizable.
let thing = Thing()
// Check whether or not a class is useable
if let usableThing = thing as Usable { // error here
usableThing.use()
}
else {
println("can''t use that")
}
Pero me sale el error
Bound value in a conditional binding must be of Optional Type
Si lo intento
let thing:Thing? = Thing()
Me sale el error
Cannot downcast from ''Thing?'' to non-@objc protocol type ''Usable''
Luego agrego @objc
al protocolo y obtengo el error
Forced downcast in conditional binding produces non-optional type ''Usable''
¿En qué punto agrego ?
Después del as
, que finalmente soluciona el error.
¿Cómo puedo lograr esta funcionalidad con el enlace condicional con un protocolo que no sea @objc, el mismo que en el video de la WWDC 2014 "Advanced Swift"?
¿Puedes compilarlo haciendo el reparto como Usable? En lugar de como utilizable, como este:
// Check whether or not a class is useable
if let usableThing = thing as Usable? { // error here
usableThing.use()
}
else {
println("can''t use that")
}
Como se menciona en el documento Swift, el operador es la persona que necesita para el trabajo:
El operador es verifica en tiempo de ejecución para ver si la expresión es del tipo especificado. Si es así, devuelve verdadero; De lo contrario, devuelve falso.
El cheque no debe ser conocido como verdadero o falso en el momento de la compilación.
Por lo tanto, la siguiente prueba normalmente sería lo que necesitas:
if thing is Usable {
usableThing.use()
} else {
println("can''t use that")
}
Sin embargo, como especifica el documento, Swift puede detectar en el momento de la compilación que la expresión siempre es verdadera y declara un error para ayudar al desarrollador.
Esto me funciona en el patio de recreo.
protocol Usable {
func use()
}
class Thing: Usable {
func use () {
println ("you use the thing")
}
}
let thing = Thing()
let testThing : AnyObject = thing as AnyObject
if let otherThing = testThing as? Thing {
otherThing.use()
} else {
println("can''t use that")
}
Los protocolos swift no funcionan en Playgrounds en la primera versión beta, en su lugar, intente construir un proyecto real.
Te estás poniendo
Bound value in a conditional binding must be of Optional Type
porque thing as Usable
debe devolver un tipo opcional para que sea as?
Debería resolver el problema. Desafortunadamente, el error aún persistió por alguna extraña razón. De todos modos, una solución que encontré para hacer que funcione es extraer la asignación de variables dentro de la sentencia if
let thing = Thing()
let usableThing = thing as? Usable
if useableThing {
usableThing!.use()
}
else {
println("can''t use that")
}