无法转换类型' NSTaggedPointerString'到' NSNumber'

时间:2015-10-23 09:37:33

标签: ios swift double nsjsonserialization

我有一个像这样的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响应。这是jsonDict变量的println。

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

当我尝试将totalfup的值分配给属性totalData时,我收到此错误。

无法转换类型' NSTaggedPointerString'的值到' NSNumber'

任何人都知道为什么?我尝试将属性类型更改为float,然后将整个结构更改为类,但问题仍然存在。

7 个答案:

答案 0 :(得分:96)

错误的原因是jsonDict["totalfup"]是一个字符串(NSTaggedPointerStringNSString的子类),所以你应该将String转换为Double。

请确保在强制解包前捕捉异常并检查类型!

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

为安全起见,请使用if let

if let totalfup = (dict["totalfup"] as? NSString)?.doubleValue {
  // here, totalfup is a Double
}
else {
  // dict["totalfup"] isn't a String
}

答案 1 :(得分:16)

我认为这可以帮到你

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

答案 2 :(得分:4)

失败的原因是JSON返回String值,而不是数字。

如果返回的JSON数据仅包含这两个键值对,则将类型声明为[String:String],以避免类型转换。

在任何情况下,您都必须将代码更新为" good" 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)")
        }
    }
}

答案 3 :(得分:0)

已测试并可以在Swift 5.0中使用。

我有同样的问题。

这对我有用。

// check dict["dummy"] is a String first
if let receivedData = (dict["dummy"]).doubleValue {
  // add more code in case the condition is true
}
else {
 // add more code in case the condition is false
}

当您想要比较接收到的数据或仅检查值时(如以下示例),这真的很有帮助。

let receivedData = (results["data"]!).doubleValue

if (receivedData == 0){
      self.label.text = "Nothing seem to be added yet!"
}

答案 4 :(得分:0)

字符串插值

我发布了my answer in a similar thread

if let jsonDict_any = jsonDict["totalfup"], 
   let jsonDict_double = Double("\(jsonDict_any)") {
   //..
}

本质上,这避免了必须尝试多个类型转换。首先检查它是否存在,然后我们可以使用字符串插值,然后尝试将其转换为 Double。

警告:

正如@Alexander 指出的那样,该解决方案允许 any Type 成为 String 并检查 Double 值。仅当您不关心插值之前值的 Type 时才使用它。

答案 5 :(得分:-1)

为什么不直接使用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
    */
}

答案 6 :(得分:-2)

雨燕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
    }
}