Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: Checking type of a dictionary value

I would like to check the type of a dictionary value, and I use the following test code:

let swiftDict = [1: "one", 2: "two"]

if swiftDict[1] is NSString {
    println("it's an nsstring")
}

I got Compiler warning: "Cast from 'String?' to unrelated NSString always fails.

Modified the code to the following:

if let str = swiftDict[1] as? NSString? {
    println("it's an nsstring")
}

Now I get Compiler warning: Conditional cast from String? to NSString? always succeeds.

How do I fix the above warning? What's the right way to check for a variable type?

The reason for the check is to find out whether String or NSString is stored.

like image 429
Boon Avatar asked Sep 21 '25 10:09

Boon


2 Answers

If you have a dictionary with mixed types (i.e. value:AnyObject) you could iterate through them and use is to check what type a value in the dictionary is, e.g.

let swiftDict:[Int:AnyObject] = [1: "one", 2: "two", 3: 15, 4: true]
for (key, value) in swiftDict
{
    if (value is String)
    {
        println("\(key): \(value) is String")
    }
}
like image 117
BadmintonCat Avatar answered Sep 23 '25 01:09

BadmintonCat


Why do you want to test your value type at all, as Swift is already type-safe?

Contrary to Objective-C, arrays and dictionaries in Swift are typed. So your swiftDict variable is of type Dictionary<Int, String> (or [Int:String] for short) and thus the values of this dictionary will always be Strings, by definition.

For example, if you had tried to write this:

let swiftDict = [1: "one", 2: "two", 3: 7]
// error: '_' is not convertible to 'StringLiteralConvertible'

Then the compiler would error, telling you that 7 is not of type String nor convertible to a String, so you can't add it to swiftDict, which is inferred to be of type [Int:String]

This means that, by definition, swiftDict[1] will always be a String (because swiftDict is a [Int:String])… or nil if there is no key 1 in that dict.

--> swiftDict[1] is guaranteed to be of type String?. So you don't even need to test the type cast. You just need to test if it's nil or not.

if let value = swiftDict[1] {
    println("swiftDict has a string value of \(value) for key 1")
} else {
    println("swiftDict does not have the key 1")
}

[EDIT] Also note that String and NSString are toll-free bridged, which means that they are totally interchangeable. So you don't even need to test or cast if your String is an NSString, as it will always be possible to cast from String to NSString and vice-versa (it will always be possible to interpret your string either as String or NSString).

like image 27
AliSoftware Avatar answered Sep 23 '25 02:09

AliSoftware