web-dev-qa-db-fra.com

La valeur liée dans une liaison conditionnelle doit être de type facultatif

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?

19
JuJoDi

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")
}
33
Connor

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")
}
1
David Arve

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. 

1
Jean Le Moignan

Les protocoles Swift ne fonctionnent pas dans Playgrounds dans la première version bêta, essayez plutôt de construire un vrai projet.

0
user3722125

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")
}
0
Infinity