I have a protocol defined:
protocol Usable {
func use()
}
and a class that conforms to that protocol
class Thing: Usable {
func use () {
println ("you use the thing")
}
}
I would like to programmatically test whether or not the Thing class conforms to the Usable protocol.
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")
}
But I get the error
Bound value in a conditional binding must be of Optional Type
If I try
let thing:Thing? = Thing()
I get the error
Cannot downcast from 'Thing?' to non-@objc protocol type 'Usable'
I then add @objc
to the protocol and get the error
Forced downcast in conditional binding produces non-optional type 'Usable'
At which point I add ?
after the as
, which finally fixes the error.
How can I achieve this functionality with conditional binding with a non-@objc protocol, the same as in the "Advanced Swift" 2014 WWDC Video?
You can get it to compile by making the cast as Usable? instead of as Usable, like this:
// Check whether or not a class is useable
if let usableThing = thing as Usable? { // error here
usableThing.use()
}
else {
println("can't use that")
}
As metioned in the Swift doc, the is
operator is the guy you need for the job:
The is operator checks at runtime to see whether the expression is of the specified type. If so, it returns true; otherwise, it returns false.
The check must not be known to be true or false at compile time.
Therefore, the following test would normally be what you need:
if thing is Usable {
usableThing.use()
} else {
println("can't use that")
}
However, as the doc specifies, Swift can detect at compile time that the expression is always true and declares an error to help the developer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With