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


у меня есть быстрая структура, как это.

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 переменной.

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

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

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

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

5 55

5 ответов:

причина ошибки jsonDict["totalfup"] - это строка, поэтому вы должны преобразовать строку в Double.

пожалуйста, убедитесь, поймать исключение и проверить тип перед force-unwrap

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

для безопасности, с помощью if let:

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

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

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

причина сбоя заключается в том, что 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)")
        }
    }
}

почему бы не использовать собственные типы 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
    }
}