无法将 'NSTaggedPointerString' 类型的值转换为 'NSNumber'
Could not cast value of type 'NSTaggedPointerString' to '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 响应。这是 jsonDict
变量的 println。
[
"totalfup": 96.340899,
"totalrem": 3548710948
]
当我尝试将 totalfup
的值分配给 属性 totalData
时,出现此错误。
无法将类型 'NSTaggedPointerString' 的值转换为 'NSNumber'
有人知道为什么吗?我尝试将 属性 类型更改为 float
,然后将整个结构更改为 class,但问题仍然存在。
错误的原因是jsonDict["totalfup"]
是一个String(NSTaggedPointerString
是NSString
的子类),所以你应该将String转换成Double。
请确保在强制展开之前捕获异常并检查类型!
totalData = (jsonDict["totalfup"] as! NSString).doubleValue
为了安全,使用if let
:
// check dict["totalfup"] is a String?
if let totalfup = (dict["totalfup"] as? NSString)?.doubleValue {
// totalfup is a Double here
}
else {
// dict["totalfup"] isn't a String
// you can try to 'as? Double' here
}
失败的原因是 JSON returns String
值,而不是数字。
如果返回的JSON数据只包含这两个键值对,声明类型为[String:String]
,避免类型转换。
在任何情况下,您都必须将更新变量的代码放入 do - catch
表达式的 "good" 分支中。
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)")
}
}
}
我想这对你有帮助
totalData = Double(jsonDict["totalfup"] as! String)!
为什么不直接使用 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
*/
}
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
}
}
已针对 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!"
}
字符串插值
我发布了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
时才使用它。
我有一个这样的 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
,然后将整个结构更改为 class,但问题仍然存在。
错误的原因是jsonDict["totalfup"]
是一个String(NSTaggedPointerString
是NSString
的子类),所以你应该将String转换成Double。
请确保在强制展开之前捕获异常并检查类型!
totalData = (jsonDict["totalfup"] as! NSString).doubleValue
为了安全,使用if let
:
// check dict["totalfup"] is a String?
if let totalfup = (dict["totalfup"] as? NSString)?.doubleValue {
// totalfup is a Double here
}
else {
// dict["totalfup"] isn't a String
// you can try to 'as? Double' here
}
失败的原因是 JSON returns String
值,而不是数字。
如果返回的JSON数据只包含这两个键值对,声明类型为[String:String]
,避免类型转换。
在任何情况下,您都必须将更新变量的代码放入 do - catch
表达式的 "good" 分支中。
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)")
}
}
}
我想这对你有帮助
totalData = Double(jsonDict["totalfup"] as! String)!
为什么不直接使用 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
*/
}
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
}
}
已针对 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!"
}
字符串插值
我发布了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
时才使用它。