在swift4.1中将Any强制转换为Float总是失败 [英] Cast Any to Float always fails in swift4.1
问题描述
在以前的版本中,要从[String: Any]
字典中获取浮点值,我可以使用let float = dict["somekey"] as? Float
,但是在swift4.1中,它不起作用.在我得到dict["somekey"]
的类型之前,它似乎已经隐式地推断为Double
,因此从Double
强制转换为Float
总是失败.我想知道这是一个新特性还是一个错误.
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 doesn't work. It seems the type of dict["somekey"]
has been implicitly inferred as Double
before I get it, so casting from Double
to Float
always fails. I wonder if it is a new characteristic or just a bug.
-这是更新.
我重新下载了Xcode9.2,并做了一些实验,现在我想我知道发生了什么.这是测试代码:
I re-downloadeded an Xcode9.2 and did some experiments, now I think I figure out what's going on. Here is the test code:
let dict: [String : Any] = ["key": 0.1]
if let float: Float = dict["key"] as? Float {
print(float)
} else {
print("nil")
}
let dict1: [String : Any] = ["key": NSNumber(value: 0.2)]
if let float: Float = dict1["key"] as? Float {
print(float)
} else {
print("nil")
}
let number = NSNumber(value: 0.3)
if let float: Float = number as? Float {
print(float)
} else {
print("nil")
}
let number1 = NSNumber(floatLiteral: 0.4)
if let float = number1 as? Float {
print(float)
} else {
print("nil")
}
在Swift4和Swift4.1的Playground中运行此代码,结果是不同的.在Swift4中,结果为nil
0.2
0.3
0.4
,在Swift4.1中,结果为nil
nil
nil
nil
.从结果中,我可以学到两点:
1.当我们使用JSONSerialization
类将JSON数据转换为[String : Any] dictionary
时,数值将保存为NSNumber
对象,但不保存为Int
,Double
或Float
.
2.在Swift4中,我们可以使用let float = NSNumberOjbect as? Float
来获取Float
值,但是在Swift4.1中则不能.但是,仍然可以通过这种方式在Swift4或Swift4.1中获得Int
或Double
值.
最后,这是一个新功能还是一个错误?如果有人知道,你们可以显示公告链接吗?
Running this code in Playground of Swift4 and Swift4.1, the results are different. In Swift4, the results are nil
0.2
0.3
0.4
, and In Swift4.1 the results are nil
nil
nil
nil
. From the result, I can learn two points:
1. When we convert JSON data into a [String : Any] dictionary
with the JSONSerialization
class, the numeric value is saved as an NSNumber
object, but not Int
, Double
or Float
.
2. In Swift4, we can use let float = NSNumberOjbect as? Float
to get a Float
value, but in Swift4.1 we can't. But still, we can get Int
or Double
value in this way, either in Swift4 or Swift4.1.
Finally again, is this a new feature or a bug? If someone knows, can you guys show up the announcement link?
推荐答案
您需要区分两种情况(在Swift 3中是三种情况):
You need to distinguish two cases (in Swift 3, it was three cases):
-
Any
包含Swift本机Double
-
Any
包含NSNumber
Any
containing a Swift nativeDouble
Any
containing anNSNumber
(In Swift 3, there was type preserving NSNumber
case other than the normal NSNumber
.)
创建诸如[String: Any]
之类的本机Swift Dictionary
时,在更新中以常规方式设置Double
值:
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]
在这种情况下,Any
将表示Double
的元数据和原始值0.1
保留为Double
.
In this case, Any
holds the metadata representing Double
and the raw value 0.1
as Double
.
并且将Double
保持为Float
的强制转换Any
总是失败.由于Double
到Float
不能用as
-castings转换.
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
但是,在Any
保持NSNumber
的情况下,就像从NSArray
或NSDictionary
桥接Array
或Dictionary
时一样,在以前的Swifts和Swift 4.1之间,行为是不同的.
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.
JSONSerialization
的结果与此情况匹配.
The result of JSONSerialization
matches this case.
在以前的Swift中,(正常)从NSNumber
到Float
是总是成功的操作.
In former Swifts, (normal) NSNumber
to Float
was an always-success operation.
在Swift 4.1中,行为随着我在注释中显示的新功能而改变:
And in Swift 4.1, the behavior has changed with the new feature which I have shown in my comment:
SE-0170 NSNumber桥接和数字类型
我省略了在Swift 3中发现的第三种情况,它已经过去了.
I omit the third case once found in Swift 3, it's past.
但是,非常重要的是如何获取Dictionary
或Array
以及如何为其设置值,以解决Any
到Float
的问题.
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.
这篇关于在swift4.1中将Any强制转换为Float总是失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!