2015-10-23 8 views
51

Ich habe eine Swift-Struktur wie diese.Konnte den Wert vom Typ 'NSTaggedPointerString' nicht in 'NSNumber' umwandeln

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

Von einer API erhalte ich die folgende JSON-Antwort. Dies ist der Ausdruck der Variablen jsonDict.

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

Wenn ich versuche, den Wert der totalfup die Eigenschaft zuweisen totalData, bekomme ich diesen Fehler.

kann nicht Wert vom Typ 'NSTaggedPointerString' gießen 'NSNumber'

Wer weiß, warum? Ich habe versucht, den Eigenschaftstyp auf float und dann die gesamte Struktur in Klasse zu ändern, aber immer noch tritt das Problem auf.

Antwort

77

Der Grund des Fehlers ist jsonDict["totalfup"] ist ein String, also sollten Sie String in Double konvertieren.

Bitte stellen Sie sicher, Ausnahme fangen und prüfen Art vor kraft unwrap

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

Für einen sicheren, mit if let:

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

Vielen Dank! Das hat funktioniert. Weißt du warum das so ist? Zurück in Swift 1.2 mussten wir nicht zu 'NSString' konvertieren, oder? – Isuru

+0

Ich bin mir nicht sicher über Swift 1.2. "NSJSONSerialization" deserialisiert manchmal den Zahlenwert als Zahl. Bevor Sie Werte von 'NSDecimalNumber 'konvertieren, sollten Sie zuerst [Objektklasse] (dynamicType) überprüfen. – anhtu

+0

Ich habe den gleichen Fehler mit einem Framework, das ich verwendete, das liest Konfigurationswerte aus einer benutzerdefinierten PLIST-Datei in den Ressourcen des Bundles (kein JSON beteiligt). Ich hatte einige der Plist-Felder als 'String' definiert, aber die API erwartete wahrscheinlich, dass sie' Number's waren. Durch Ändern des Typs in "Number" wurde das Problem behoben. –

3

Die Störungsursache ist, dass die JSON String Werte zurückgibt, keine Zahlen.

Wenn die zurückgegebenen JSON-Daten nur diese beiden Schlüsselwertpaare enthalten, deklarieren Sie den Typ als [String:String], wodurch das Typcasting vermieden wird.

In jedem Fall müssen Sie den Code setzen, um die Variablen in den "guten" Zweig des Ausdrucks do - catch zu aktualisieren.

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

Danke für die Antwort. Aber ich kann nicht einfach 'Double (jsonDict [" totalfup "])' als ich diesen Fehler bekomme. ** Initialisierer für Typ 'Double' mit einer Argumentliste vom Typ '(AnyObject?)' ** kann nicht aufgerufen werden. Ich denke, Sie müssen den Schlüsselwertpaartyp als '[String: Double]' definieren, damit dies funktioniert. – Isuru

+0

Wenn 'jsonDict' in' [String: String] 'umgewandelt wird (siehe Ende der' NSJSONSerialization' Zeile in meiner Antwort), kann der Compiler nicht annehmen, dass es 'AnyObject' ist.Allerdings habe ich die Ausrufezeichen vergessen yo die Werte auspacken – vadian

+0

@vadian Bitte aktualisieren Sie Ihre Antwort, sonst wird es nicht kompilieren ... (alle Eigenschaften müssen initialisiert werden) – user3441734

13

ich denke, das Sie

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

warum nicht direkt Swift native Typen helfen könnte verwenden?

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