Boon
Boon

Reputation: 41510

Type check in Swift

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

Answers (2)

GoZoner
GoZoner

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

Martin R
Martin R

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

Related Questions