Reputation: 41510
I am not able to do the following type check that I thought should work:
var str:String?
//Compiler error: Downcast from 'String?' to 'String' only unwraps optional; did you mean to use '!'?
if str is String {
}
//Compiler error: is test is always true
if str! is String {
println("str is optional string")
}
Upvotes: 1
Views: 1467
Reputation: 70235
Your str
is a String?
which is an optional; an optional can never be a String
as it is a wholly distinct type. Thus if str is String
can never be true and the compiler tells you about it.
Similarly str!
unwraps Sting?
and the result is always String
. Thus if str! is String
is always true.
The use of is
is illustrated with:
class Shape {}
class Rectangle : Shape {}
class Circle : Shape {}
func draw (s:Shape) {
if s is Rectangle {}
else if s is Circle {}
else {}
}
In the draw
function, the compiler recognizes that Rectangle
and Circle
are subtypes of the arguments Shape
type and therefore the if
statements are allowed.
Upvotes: 0
Reputation: 540055
From "Type-Casting Operators" in the Swift documentation (emphasis mine):
The is operator checks at runtime whether the expression can be downcast to the specified type. It returns true if the expression can be downcast to the specified type; otherwise, it returns false. If casting to the specified type is guaranteed to succeed or fail, a compile-time error is raised.
String
is not a proper subclass of String?
or String
, therefore the is
operator cannot be used here. And to check if str
has a value one would use
an optional assigment instead: if let theString = str { ... }
.
Working examples:
class A { }
class B : A { }
func foo(a : A) {
if a is B {
// a is an instance of the B subclass
}
}
func bar(obj: AnyObject) {
if obj is NSNull {
// The Null object
}
}
In many cases the conditional cast as?
is more useful because it returns an
a value of the specified type:
func foo(a : A) {
if let b = a as? B {
// ...
}
}
Upvotes: 6