J'ai un protocole défini:
protocol Usable {
func use()
}
et une classe conforme à ce protocole
class Thing: Usable {
func use () {
println ("you use the thing")
}
}
Je voudrais tester par programme si la classe Thing est conforme au protocole utilisable.
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")
}
Mais j'ai l'erreur
Bound value in a conditional binding must be of Optional Type
Si j'essaye
let thing:Thing? = Thing()
Je reçois l'erreur
Cannot downcast from 'Thing?' to non-@objc protocol type 'Usable'
J'ajoute ensuite @objc
au protocole et j'obtiens l'erreur
Forced downcast in conditional binding produces non-optional type 'Usable'
A ce stade, j'ajoute ?
après la as
, ce qui corrige finalement l'erreur.
Comment obtenir cette fonctionnalité avec une liaison conditionnelle avec un protocole autre que @ objc, identique à celui de la vidéo WWDC "Advanced Swift" 2014?
Vous pouvez le compiler en rendant le casting utilisable? au lieu de comme utilisable, comme ceci:
// Check whether or not a class is useable
if let usableThing = thing as Usable? { // error here
usableThing.use()
}
else {
println("can't use that")
}
Cela fonctionne pour moi dans la cour de récréation
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")
}
Comme indiqué dans la documentation Swift, l'opérateur is
est le type dont vous avez besoin pour le travail:
L'opérateur is vérifie au moment de l'exécution si l'expression est de le type spécifié. Si c'est le cas, cela retourne vrai; sinon, il retourne faux.
La vérification ne doit pas être connue pour être vraie ou fausse au moment de la compilation.
Par conséquent, le test suivant correspond normalement à vos besoins:
if thing is Usable {
usableThing.use()
} else {
println("can't use that")
}
Toutefois, comme le spécifie la documentation, Swift peut détecter au moment de la compilation que l'expression est toujours vraie et déclare une erreur pour aider le développeur.
Les protocoles Swift ne fonctionnent pas dans Playgrounds dans la première version bêta, essayez plutôt de construire un vrai projet.
Vous obtenez
Bound value in a conditional binding must be of Optional Type
parce que thing as Usable
doit renvoyer un type facultatif, il est donc résolu de résoudre le problème avec as?
. Malheureusement, l'erreur a persisté pour une raison étrange. Quoi qu'il en soit, une solution de contournement que j'ai trouvée pour que cela fonctionne consiste à extraire l'affectation de variable à l'intérieur de l'instruction if
let thing = Thing()
let usableThing = thing as? Usable
if useableThing {
usableThing!.use()
}
else {
println("can't use that")
}