Swift将字典值作为类型

时间:2015-03-11 13:01:10

标签: swift dictionary types casting

我正在寻找最好的方法如何将此代码改为一行:

if (dictionary["Amoumt"] is Double) {
    amount = dictionary["Amount"] as Double
} else {
    amount = NSString(string: dictionary["Amount"] as String).doubleValue
}

我有Dictionary<String, AnyObject>,我想解析它的值。我正在使用上面的代码但它的行太多了。我想把它变成一条线。类似的东西:

dictionary["Amount"].parseDouble()

使用此方法创建扩展程序没有问题:

func parseDouble() -> Double {
    if (self is Double) {
        return self as Double
    } else {
        return NSString(string:(self as String)).doubleValue
    }
}

但是我应该扩展哪种类型?接下来你能用通用方法帮我吗?所以我可以这样说:

dictionary["Amount"].parse(Double)

这是如何做到这一点的好方法,还是我应该采取另一种方式?

4 个答案:

答案 0 :(得分:1)

也许你正在寻找这种扩展:

extension Dictionary{

    func parseDouble(key:Key) -> Double {

        let result = self[key]

        if (result is Double) {
            return result as Double
        } else {
            return NSString(string:(result as String)).doubleValue
        }
    }
}

使用以下方法获取密钥的价值:

var doubleValue = dictionary.parseDouble("amount")

一个通用函数

extension Dictionary{

    func parse<T>(key:Key) -> T? {

        let result = self[key]

        if (result is T) {
            return result as? T
        }

        return nil
    }
}

var doubleValue:Double? = myDistionary.parse("someKeyForDouble")

var stringValue:String? = myDistionary.parse("someKeyForString")

答案 1 :(得分:1)

您可以按原样使用AnyObject。尝试:

var dictionary:[String:AnyObject] = [
    "foo": 4.21,    // NSNumber
    "bar": "42.5",  // NSString
    "baz": [1,2,3], // NSArray
]

let foo = dictionary["foo"]?.doubleValue ?? 0 // -> 4.21
let bar = dictionary["bar"]?.doubleValue ?? 0 // -> 42.5
let baz = dictionary["baz"]?.doubleValue ?? 0 // -> 0.0

这是有效的,因为NSNumberNSString都有.doubleValue属性。 另一方面,NSArray没有该属性,在这种情况下,它返回nil

the document中所述:

  

您还可以调用任何Objective-C方法并访问任何属性,而无需转换为更具体的类类型。这包括标有@objc属性的Objective-C兼容方法。

答案 2 :(得分:0)

最简单的方法是使用nil合并运算符和可选的double。这会尝试将值转换为double。如果成功,则将其解包,如果失败,则默认为第二个值,即转换为“dict [amount]&#39;到一个字符串并取其双倍值。

var amount: Double? = nil

let dict: [String: AnyObject] = ["amount" : "1.2"]

amount = (dict["amount"] as? Double) ?? NSString(string: dict["amount"] as! String).doubleValue

为了实现你的功能:

func getDouble(obj: AnyObject) -> Double {
    return (obj as? Double) ?? NSString(string: obj as! String).doubleValue
}

然后使用getDouble(dict["amount"])调用它。对我这样的事情的延伸可能在我看来有点过分了。

答案 3 :(得分:0)

如果你想要一个扩展名,那么理论上最好的地方就是AnyObject - 因为它是你要转换的AnyObject

但是AnyObject实际上是一个协议,所以你无法扩展它。

我不建议将它作为Dictionary的扩展名 - 将类型强制转换为双精灵并不是与字典有任何关系。

所以最好的方法是将它作为自由函数而不是作为扩展:

func getDouble(obj: AnyObject?) -> Double {
    return (obj as? Double) ?? (obj as? NSString)?.doubleValue ?? 0
}
asDouble(dictionary["Amount"])

注意,如果你传递一个既不是double也不是字符串的函数,这个函数是安全的。使用as!而不是as?的其他解决方案在运行时会因为其他内容传递而崩溃。

你可以说它应该返回一个可选项,如果该值不能转换为double,则返回nil。这就是String.toInt()的作用。不幸的是,NSString.doubleValue的限制是它没有这样做 - 它默认为零 - 所以你不能将这两种方法结合起来。