In the former version, to get a float value from a [String: Any]
dictionary, I can use let float = dict[\"somekey\"] as? Float
, but in swift4.1, it
You need to distinguish two cases (in Swift 3, it was three cases):
Any
containing a Swift native Double
Any
containing an NSNumber
(In Swift 3, there was type preserving NSNumber case other than the normal NSNumber
.)
When you create a native Swift Dictionary
such as [String: Any]
, and set Double
value in a normal way like this in your update:
let dict: [String : Any] = ["key": 0.1]
In this case, Any
holds the metadata representing Double
and the raw value 0.1
as Double
.
And casting Any
holding Double
to Float
always fails. As Double
to Float
cannot be converted with as
-castings.
let dblValue: Double = 0.1
if let fltValue = dblValue as? Float { //<-Cast from 'Double' to unrelated type 'Float' always fails
print(fltValue)
} else {
print("Cannot convert to Float")
}
//->Cannot convert to Float
But, in case of Any
holding NSNumber
, as always happens when the Array
or Dictionary
is bridged from NSArray
or NSDictionary
, the behaviors are different between former Swifts and Swift 4.1.
The result of JSONSerialization
matches this case.
In former Swifts, (normal) NSNumber
to Float
was an always-success operation.
And in Swift 4.1, the behavior has changed with the new feature which I have shown in my comment:
SE-0170 NSNumber bridging and Numeric types
I omit the third case once found in Swift 3, it's past.
But it is very important how you get your Dictionary
or Array
, and how you set the value to them, to solve the issue Any
to Float
.
Finally again, is this a new feature or a bug? If someone knows, can you guys show up the announcement link?
This is a new feature, not a bug. See the link above, and related threads below.
Unable to bridge NSNumber to Float Swift 3.3
Unexpected behavior when casting an NSNumber to Float