Предположим, я получаю данные в каком-то 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
для чего-то столь же тривиального, как это? Я упускаю что-то очень очевидное здесь, верно?