If I have an implicitly unwrapped optional declared in my class which I then reference in a Dictionary
of type [String : Any]
, it doesn\'t get unwr
Under the rules set out by SE-0054, IUOs are only force unwrapped in contexts that demand their unwrapped type. In your case, the IUO doesn't need to be force unwrapped in order to be coerced to Any
(as Any
can represent any value), so it isn't.
This behaviour is discussed in more detail in these Q&As:
The fact that you end up with an ImplicitlyUnwrappedOptional
value in your dictionary is legacy behaviour that has been removed in the latest Swift snapshots, in the future you will end up with an Optional
value instead (as IUO is no longer a type).
One important thing to note here however (that I'm sure will trip up people) is that the printing of IUOs got changed in 4.1.
In Swift 4.0.3, your example prints like this:
var aString: String! = "hello"
var params : [String : Any] = [
"myString" : aString
]
print(params)
// This prints ["myString": hello]
giving you the illusion that the IUO was force unwrapped when coerced to Any
. This however is just how IUOs were printed in Swift 4.0.3 – if they had a value, then they would print as that value, otherwise they would print as nil
:
var aString: String! = nil
var params : [String : Any] = [
"myString" : aString
]
print(params)
// This prints ["myString": nil]
The reason why this changed in Swift 4.1 is that ImplicitlyUnwrappedOptional
's conformance to Custom(Debug)StringConvertible
was removed in this commit in order to make progress towards removing the type itself. So now ImplicitlyUnwrappedOptional
values get printed using Swift's default printing mechanism (using reflection).
So, in a dictionary, you get the IUO's default debugDescription
, which looks like this:
let aString: String! = "hello"
let params : [String : Any] = [
"myString" : aString
]
print(params)
// This prints ["myString": Swift.ImplicitlyUnwrappedOptional<Swift.String>.some("hello")]
If you had printed it on its own, you would get its default description
, which looks like this:
let aString: String! = "hello"
print(aString) // some("hello")
This is because in Swift 4.1, the ImplicitlyUnwrappedOptional
type is implemented in the same way as Optional
, an enumeration with two cases:
public enum ImplicitlyUnwrappedOptional<Wrapped> : ExpressibleByNilLiteral {
// The compiler has special knowledge of the existence of
// `ImplicitlyUnwrappedOptional<Wrapped>`, but always interacts with it using
// the library intrinsics below.
/// The absence of a value. Typically written using the nil literal, `nil`.
case none
/// The presence of a value, stored as `Wrapped`.
case some(Wrapped)
// ...
}
For an IUO with a payload value, Swift's default reflection will therefore print it as the case some
containing the wrapped value.
But this is only temporary; the IUO type is currently (in Swift 4.1) deprecated, however it will be removed in Swift 4.2. The compiler was internally using the IUO type in quite a few places, which took quite a bit of work to remove. Therefore in 4.2 you'll have actual Optional
values in your dictionary, which will print like Optional("hello")
.
When you define a dictionary of type
let dictionary = [String:Any]()
you can put anything in this dictionary
like
dictionary["name"] = "xyz"
and
dictionary["code"] = 123
while in
let dictionary = [String:String]()
you can only put an only string value
that's why you have to unwrap value when you are accessing the value because it can be anyting
Change this line:
var params : [String : Any] = ["myString" : aString]
to:
var params : [String : String] = ["myString" : aString]
Any
can represent an instance of any type at all, including function types and optional types.AnyObject
can represent an instance of any class type.And your aString
is an instance object which should not be use to declare in property Area, if you put that line in any function/instance function()
then it will work perfectly, because it will be your instance type then.
In One word, you can not declare instance type in property area in Swift.
override func viewDidLoad() {
let params : [String : Any] = ["myString": aString]
}
Even in Property Area, You can not do like following:
var aString: String! = "String"
var abc = aString
You have to abc = aString
do in any Method()
to get work.
Hope it will help you.