【发布时间】:2018-05-15 10:29:25
【问题描述】:
假设我收到一些 JSON 格式的数据,然后使用本机工具将其解析为字典。其中一些值是数字,我自然需要解析它们,将它们转换为我在应用程序中需要的值。
但是从Any 到Float、Int、Double 等实际数字的转换似乎有点混乱。例如,如果我期望一个双精度,但在某些时候服务器返回一个整数,我的代码将失败使用:
let doubleValue = dictionary["key"] as! Double
因此,当项目为 1.3 时这将起作用,但对于 1 将失败。要使用更具体的示例,我们可以使用以下内容:
let myDictionary: [String: Any] = [
"myNumber_int" : 1,
"myNumber_float" : Float(1),
"myNumber_cgFloat" : CGFloat(1),
"myNumber_double" : 1.0
]
let numberInt1 = myDictionary["myNumber_int"] as? Int // 1
let numberInt2 = myDictionary["myNumber_int"] as? Float // nil
let numberInt3 = myDictionary["myNumber_int"] as? CGFloat // nil
let numberInt4 = myDictionary["myNumber_int"] as? Double // nil
let numberFloat1 = myDictionary["myNumber_float"] as? Int // nil
let numberFloat2 = myDictionary["myNumber_float"] as? Float // 1
let numberFloat3 = myDictionary["myNumber_float"] as? CGFloat // nil
let numberFloat4 = myDictionary["myNumber_float"] as? Double // nil
let numberCGFloat1 = myDictionary["myNumber_cgFloat"] as? Int // nil
let numberCGFloat2 = myDictionary["myNumber_cgFloat"] as? Float // nil
let numberCGFloat3 = myDictionary["myNumber_cgFloat"] as? CGFloat // 1
let numberCGFloat4 = myDictionary["myNumber_cgFloat"] as? Double // nil
let numberDouble1 = myDictionary["myNumber_double"] as? Int // nil
let numberDouble2 = myDictionary["myNumber_double"] as? Float // nil
let numberDouble3 = myDictionary["myNumber_double"] as? CGFloat // nil
let numberDouble4 = myDictionary["myNumber_double"] as? Double // 1
因此,对于每种类型,实际上只有 1 个演员可以工作,这是……好吧,我至少希望 CGFloat 能够直接转换为 Double 或 Float……
所以我的解决方案是使用NSNumber:
let myNumbers: [CGFloat] = [
CGFloat((myDictionary["myNumber_int"] as? NSNumber)?.floatValue ?? 0.0),
CGFloat((myDictionary["myNumber_float"] as? NSNumber)?.floatValue ?? 0.0),
CGFloat((myDictionary["myNumber_cgFloat"] as? NSNumber)?.floatValue ?? 0.0),
CGFloat((myDictionary["myNumber_double"] as? NSNumber)?.floatValue ?? 0.0),
] // [1,1,1,1]
这自然可行,但是对于像这样简单的事情,代码非常难看。但是把代码“丑陋”放在一边;如果不使用 Next Step,我们可以不做类似的事情吗?我的意思是NSNumber 像这样看似微不足道的事情?我在这里遗漏了一些非常明显的东西,对吧?
【问题讨论】:
-
您是否必须“使用本机工具”解析 JSON?你不能用
JSONDecoder和Codable吗? -
当你从某处得到
JSON时,整数值为Int,流动点值为Double,句号。如果您的解析器创建更多类型,请使用更好的解析器或考虑 Sweeper 的建议。 -
@vadian 如果 JSON 让您感到困惑,我深表歉意,但这只是一个例子。但即使只有整数和浮点数,问题仍然存在。
-
如果您创建具有具体类型的字典,即使您将字典声明为
[String:Any],这些类型仍然存在。同样,接收到的 JSON 只有两种类型。你甚至可以将1转换为Double(当然反之亦然)。 -
那么你应该在
Swift语言中使用Any。Any用于非对象或Swift中的所有类型,因此Int、Double、Float、Array、Dictionary这些都不是对象。AnyObject用于Class实例。一个问题,如果您不知道值的类型,那么您为什么要铸造。只有let numberInt2 = myDictionary["myNumber_int"]肯定会起作用。
标签: swift dictionary casting