How to cast Dictionary in Swift to related type?

3.3k Views Asked by At

This is what I am trying to do with the dictionary:

    if let deliveries = dictionary["deliveries"] as? NSDictionary {

        var castedDeliveries = [Double: Double]()

        for delivery in deliveries {

            if let value = delivery.value as? Double {
                castedDeliveries[Double(delivery.key as! NSNumber)] = value //Could not cast value of type 'NSTaggedPointerString' (0x1a1e3af20) to 'NSNumber' (0x1a1e458b0).
            }
        }
        settings!.deliveries = castedDeliveries
    }

And this is what I try to cast, as a part of JSON response from server:

deliveries =            {
    2 = 0;
    5 = "2.59";
    7 = "3.59";
};

It doesnt work, because there is an error at commented line:

Could not cast value of type 'NSTaggedPointerString' (0x1a1e3af20) to 'NSNumber' (0x1a1e458b0).

3

There are 3 best solutions below

0
On

As I noted in the comments, this isn't casting. You want a data conversion. You need to do that explicitly, especially in this case since it might fail.

Looking at the error, I think you really have a dictionary of [String:String] here (in NSDictionary form). That suggests the JSON is badly encoded, but such is life. Assuming that dictionary looks something like this:

let dictionary: NSDictionary = ["deliveries": ["2":"0", "5": "2.59", "7": "3.59"]]

You would convert it to [Double:Double] like this:

if let jsonDeliveries = dictionary["deliveries"] as? [String:String] {
    var deliveries: [Double: Double] = [:]
    for (key, value) in jsonDeliveries {
        if let keyDouble = Double(key),
            valueDouble = Double(value) {
                deliveries[keyDouble] = valueDouble
        }
    }
    // Use deliveries
}

This silently ignores any values that can't be converted to Double. If you would rather generate errors, use a guard let rather than an if let.

0
On

You are trying to cast dictionary directly but instead you need to cast each key - value pair. If you want generic solution to this problem take a look at SwiftyJSON library which address JSON parsing problem for you.

1
On

Casting doens't mean data transformation from a type to another.
Your dictionary seems to be composed by Integer keys and String values.
If you want to transform in something else you ca use the map function.

let converted = deliveries.map{[Double($0) : Double($1)]}

But pay attention.
Here we are saying, iterate over the dictionary (in the $0 there is the dictionary key in the $1 there is the value) and create a new dictionary that has as a key a Double initialized at the key value and as a new value a Double initialized as the old dictionary value. The last conversion can fail, so the returned data is an optional.