Невозможно присвоить значение типа NSTaggedPointerString 'NSNumber'

У меня такая структура Swift.

struct Usage {
    var totalData: Double
    var remainingTotalData: Double

    init(jsonData: NSData) {
        var jsonDict = [String: AnyObject]()

        do {
            jsonDict = try NSJSONSerialization.JSONObjectWithData(jsonData, options: []) as! [String: AnyObject]
        } catch {
            print("Error occurred parsing data: \(error)")
        }

        totalData = jsonDict["totalfup"] as! Double
        remainingTotalData = jsonDict["totalrem"] as! Double
    }
}

Из API я получаю следующий ответ JSON. Это println переменной jsonDict.

[
    "totalfup": 96.340899, 
    "totalrem": 3548710948
]

Когда я пытаюсь присвоить значение totalfup свойству totalData, я получаю эту ошибку.

Не удалось присвоить значение типа NSTaggedPointerString 'NSNumber'

Кто-нибудь знает, почему? Я попытался изменить тип свойства на float, а затем всю структуру на класс, но все еще проблема возникает.

Ответ 1

Причина ошибки в том, что jsonDict["totalfup"] является строкой, поэтому вам следует преобразовать строку в двойную.

Пожалуйста, убедитесь, что ловите исключение и проверяйте тип перед принудительной развертыванием

totalData = (jsonDict["totalfup"] as! NSString).doubleValue

В целях безопасности используйте if let:

if let totalfup = (dict["totalfup"] as? NSString)?.doubleValue {
}    

Ответ 2

Я думаю, это может помочь вам

totalData = Double(jsonDict["totalfup"] as! String)!

Ответ 3

Причина отказа заключается в том, что JSON возвращает значения String, а не числа.

Если возвращенные данные JSON содержат только эти две пары ключей, объявите тип как [String:String], который избегает кастования типов.

В любом случае вам нужно поместить код для обновления переменных в "хорошую" ветвь выражения do - catch.

struct Usage {
    var totalData = 0.0
    var remainingTotalData = 0.0

    init(jsonData: NSData) { // Swift 3: Data

        do {
            let jsonDict = try NSJSONSerialization.JSONObjectWithData(jsonData, options: []) as! [String: String]                
            // Swift 3: let jsonDict = try NSJSONSerialization.jsonObject(with: jsonData) as! [String: String]
            totalData = Double(jsonDict["totalfup"]!)
            remainingTotalData = Double(jsonDict["totalrem"]!)
        } catch {
            print("Error occurred parsing data: \(error)")
        }
    }
}

Ответ 4

почему бы не использовать прямые типы Swift напрямую?

import Foundation

struct Usage {
    var totalData: Double = 0
    var remainingTotalData: Double = 0

    init(jsonData: NSData) {
        do {
            if let jsonDict = try NSJSONSerialization.JSONObjectWithData(jsonData, options: []) as? [String:Double] {
                totalData = jsonDict["totalfup"] ?? 0
                remainingTotalData = jsonDict["totalrem"] ?? 0
            }
        } catch {
            print("Error occurred parsing data: \(error)")
        }
    }
}

if let data = "{\"totalfup\":96.340899,\"totalrem\":3548710948}".dataUsingEncoding(NSUTF8StringEncoding) {
    let usage = Usage(jsonData: data)
    dump(usage)
    /*
    ▿ Usage
      - totalData: 96.340899
      - remainingTotalData: 3548710948.0
    */
}

Ответ 5

Swift 4

    let strStatus:String = dictProperty.value(forKey: "StatusType") as! String
    let myStatus = Double.init(strStatus)

Обновить

extension String {
    func toDouble() -> Double? {
        let numberFormatter = NumberFormatter()
        numberFormatter.locale = Locale(identifier: "en_US_POSIX")
        return numberFormatter.number(from: self)?.doubleValue
    }

    func toInt() -> Int? {
        let numberFormatter = NumberFormatter()
        numberFormatter.locale = Locale(identifier: "en_US_POSIX")
        return numberFormatter.number(from: self)?.intValue
    }

    func toFloat() -> Float? {
        let numberFormatter = NumberFormatter()
        numberFormatter.locale = Locale(identifier: "en_US_POSIX")
        return numberFormatter.number(from: self)?.floatValue
    }

    func toBool() -> Bool? {
        let numberFormatter = NumberFormatter()
        numberFormatter.locale = Locale(identifier: "en_US_POSIX")
        return numberFormatter.number(from: self)?.boolValue
    }
}