Reputation: 2017
Here's my test code:
var myDict: [String: AnyObject] = ["k":"v"]
var a = myDict["k"]
var b = a as String
var c = myDict["k"] as String
Here's my Swift playground in Xcode6-beta6:
According to the rules of type inference, doesn't complaining about c
logically contradict not-complaining about b
?
Upvotes: 4
Views: 197
Reputation: 122449
This has to do with the fact that Dictionary
has two subscript overloads:
subscript (key: Key) -> Value?
subscript (i: DictionaryIndex<Key, Value>) -> (Key, Value) { get }
The first is the familiar one where you pass a key and it gives you an optional of the value; and you can use to set the value on a key.
The second one is less common. I believe DictionaryIndex
is a kind of iterator into the dictionary, and you can use it as a subscript to directly get the key-value pair at that iterator.
When the compiler can't find an overload that matches (in this case, the first one doesn't match because it returns an optional, which cannot be cast to non-optional String
), it just picks one arbitrarily (well, it seems arbitrary to me anyway) to show in the error. In this place, it picks the second one, which you don't recognize. That's why the error seems weird to you.
Upvotes: 1
Reputation: 154603
I believe that this is a bug. Part of what is going on here is that String
is not an object. If you change the first line to:
var myDict: [String: Any] = ["k":"v"]
then everything is fine. So, given that string is not an object, casting a variable of type AnyObject?
to a String
should definitely yield an error. And, since the compiler has already decided that a
is of type AnyObject?
it should complain about casting a
to a String
.
Note that if you change the last line to:
var c = myDict["k"] as NSString
the error goes away supporting the notion that the issue is that String
is not an object. You get the same complaint if you put an Int
as the value in the array and try to cast that to an Int
.
Update:
So the plot thickens. If you don't import Foundation
or import something that imports Foundation, then you get additional errors. Without Foundation:
So clearly some of this has to do with the dual nature of String
s as non-objects and NSString
s as objects and the ability to use String
s as NSString
s when Foundation
is imported.
Upvotes: 2
Reputation: 80265
This works.
var c = myDict["k"] as AnyObject! as String // "v"
To answer your question, the reason Swift complains could be that you are trying to do these two conversions in one go. Remember, the statement var a = myDict["k"]
contains an implicit conversion already. The implied conversion is AnyObject?
, so the above would also work like this:
var c = myDict["k"] as AnyObject? as String // "v"
Note that the above would lead to a run time error if the key "k"
where not defined. You would allow this to return nil
by casting to String?
.
Upvotes: 0