2015-10-23 22 views
51

Ho una struttura Swift come questa.Impossibile trasmettere il valore di tipo 'NSTaggedPointerString' a '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 
    } 
} 

Da un'API, ottengo la seguente risposta JSON. Questo è il codice di stampa della variabile jsonDict.

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

Quando provo ad assegnare il valore del totalfup alla proprietà totalData, ottengo questo errore.

non potresti lanciare valore di tipo 'NSTaggedPointerString' a 'NSNumber'

Chiunque sa perché? Ho provato a cambiare il tipo di proprietà a float e quindi l'intera struttura in classe, ma il problema si verifica ancora.

risposta

77

Il motivo dell'errore è jsonDict["totalfup"] è una stringa, quindi è necessario convertire String in Double.

Si prega di assicurarsi, ad eccezione cattura e la data Tipo di prima forza-unwrap

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

Per sicurezza, utilizzando if let:

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

Grazie! Ha funzionato. Sai perché è questo? Tornando a Swift 1.2, non abbiamo dovuto convertire in 'NSString's, giusto? – Isuru

+0

Non sono sicuro di Swift 1.2. Ma 'NSJSONSerialization' a volte deserializza il valore numerico come numero. Di sicuro, prima di convertire i valori da "NSDecimalNumber", prima controlliamo [object class] (dynamicType). – anhtu

+0

Ho ottenuto lo stesso errore con un framework che stavo usando che legge i valori di configurazione da un file plist personalizzato nelle risorse del bundle (nessun JSON coinvolto). Avevo definito alcuni dei campi plist come 'String's, ma probabilmente l'API si aspettava che fossero' Number's. Cambiando il tipo in 'Numero 'risolto il problema. –

3

La causa del disturbo è che il JSON restituisce String valori, non numeri

Se i dati JSON restituiti contengono solo queste due coppie di valori chiave, dichiarare il tipo come [String:String] che evita il tipo di trasmissione.

In ogni caso è necessario inserire il codice per aggiornare le variabili nel ramo "buono" dell'espressione 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)") 
     } 
    } 
} 
+0

Grazie per la risposta. Ma non posso semplicemente fare 'Double (jsonDict [" totalfup "])' quando ottengo questo errore. ** Non è possibile richiamare l'inizializzatore per il tipo "Double" con un elenco di argomenti di tipo "(AnyObject?)" **. Suppongo che tu debba definire il tipo di coppia di valori chiave come '[String: Double]' affinché funzioni. – Isuru

+0

se 'jsonDict' è castato in' [String: String] '(vedere la fine della riga' NSJSONSerialization' nella mia risposta) il compilatore non può presumere che sia 'AnyObject'.Tuttavia ho dimenticato i punti esclamativi per scartare i valori – vadian

+0

@vadian per favore aggiorna la risposta, altrimenti non verrà compilata ... (tutte le proprietà devono essere inizializzate) – user3441734

13

credo che questo potrebbe aiutare a

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

perché non utilizzare tipi nativi di Swift direttamente?

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 
    */ 
}