这是令人困惑的原因是因为as?
在Swift中有两个完全正交的含义,具体取决于上下文。当斯威夫特类型纯粹处理,as?
是一个动态转换,返回非nil
只有在类型是字面上对as?
运营商的右侧的类型的实例:
import Foundation
let dict: [String : Any] = ["Foo" : 3 as Int]
print(dict["Foo"] as? Int)
print(dict["Foo"] as? Int32)
print(dict["Foo"] as? Int64)
这对于返回Optional(3)
第一个日志,nil
为另外两个,因为类型是Int
而不是Int32
或Int64
。
然而,当该项目被铸造的类型是Objective-C的类型,那么as?
不再是严格的动态转换,而是使桥接行为:
import Foundation
let dict: [String : Any] = ["Foo" : 3 as NSNumber]
print(dict["Foo"] as? Int)
print(dict["Foo"] as? Int32)
print(dict["Foo"] as? Int64)
该返回对于所有三个日志,因为这不再是一个动态演员 - 事实上,一个NSNumber
实例不是我们尝试投入的三种类型中的任何一种的成员。相反,as?
会导致Swift到桥接 Objective-C类型NSNumber
,如果可以,则转换为适当的Swift类型。由于Swift具有桥接NSNumber
到Int
,Int32
和Int64
(以及其他数字类型的主机)的逻辑,因此我们得到所有三个日志的Optional(3)
。但是,如果您尝试将其转换为类似Decimal
的桥接逻辑没有NSNumber
桥接逻辑,则仍可获得nil
。
这方面的一个有趣的副作用是as?
没有遵循传递属性:
let foo: Int = 3
print(foo as? NSNumber as? Int64) // Optional(3)
print(foo as? Int64) // nil
无论如何,如果你投你的价值观NSNumber
首先,你应该然后能够从那里转换为任何Objective-C桥梁支持的数字类型,这可能是您的旧Swift 3代码引发的问题。或者,如果你真的知道该值应该是类型,你可以用其他的整数类型初始化之一:
let dict: [String : Any] = ["Foo" : 3 as Int]
let foo = (dict["Foo"] as? Int).map { Int32($0) }
如果您有什么具体的JSON问题,请出示JSON和你的代码正在用它来解析它。 – Sulthan
上面的代码没有显示与JSON相关的任何内容。 '[String:Any]'是“字符串的字典,绝对可以在Swift中表示的任何数据类型。“这通常用于JSON,但用NSJSONSerialization解析JSON不应该生成你在这里给出的字典。上面的任何东西都是”无意义的“,它看起来完全遵循规则,所以它可能有助于解释问题你要解决的问题JSON没有32位或64位的整数类型 –
请注意,Swift的Int匹配ObjC的NSInteger,并且(如ObjC中)是Swift中几乎所有“整数类”事物的推荐类型。除非需要进行低级交互或在32位平台上确保非常大的整数,否则特定的位宽是非常令人沮丧的,它们并不是设计用于Swift中的一般用途;它们设计用于需要非常精确的尺寸和希望在违反尺寸要求时被警告。 –