6
votes

I'm working with dictionaries in Swift which need to hold differing types of value, although the keys are pretty much all strings. This was painfully easy with Objective-C, but Swift's generally very useful type safety seems to make this more difficult.

I had been working with [String: AnyObject] dictionaries until I ran into being unable to downcast a resulting AnyObject to a Swift string, which technically isn't an object but a value type. I can make peace with this as it seems to make sense, although if there's a way around it (besides reverting to NSString objects which I don't want to do), i'd like to know it.

The logical solution to the above seems to be switching to use [String: Any] dictionaries, but in doing so I'm finding a problem even with a basic piece of code:

func abc() {
    var dict : [String: Any] = [String: Any]()
    if dict["success"] != nil {
       ...
    }
}

The 3rd line of code above gives the error:

'String' is not convertible to 'DictionaryIndex<String, Any>'.

Now I seem to have a dictionary that contains types that I suspect I can downcast as I need to, but that no longer seems accessible by its keys, which as far as I can see are of exactly the right type (indeed, although it's a literal, even the error suggests I am passing a String). What am I missing, given all I'm actually trying to achieve is dictionaries with easily accessible values of multiple types which I can actually retrieve in a var/let of the correct Swift type?

1

1 Answers

5
votes

The issue here seems to be your use of Any. Dictionary has two subscript methods:

subscript (i: DictionaryIndex<Key, Value>) -> (Key, Value) { get }
subscript (key: Key) -> Value?

The compiler incorrectly assumes you want the first one, and then complains that the String you passed in can't be converted to DictionaryIndex<Key, Value>.

To avoid this problem, you can either:

  • Force it to use a specific subscript accessor: if dict["success"] as Any? != nil ...

  • Declare your dictionary as [String:AnyObject] instead — since tuples aren't objects. From the guide,

    • AnyObject can represent an instance of any class type.

    • Any can represent an instance of any type at all, apart from function types.

If you believe this is an error, you may wish to file a bug.