2015-10-23 1 views
51

J'ai une structure Swift comme celle-ci.Impossible de convertir la valeur du type 'NSTaggedPointerString' en '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 
    } 
} 

À partir d'une API, j'obtiens la réponse JSON suivante. C'est l'println de la variable jsonDict.

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

Lorsque je tente d'affecter la valeur du totalfup à la propriété totalData, je reçois cette erreur.

Impossible jeter la valeur de type 'NSTaggedPointerString' à 'NSNumber'

Quelqu'un sait pourquoi? J'ai essayé de changer le type de propriété à float et ensuite la struct entière à la classe mais toujours le problème se produit.

Répondre

77

La raison de l'erreur est jsonDict["totalfup"] est une chaîne, vous devez donc convertir la chaîne en double.

S'il vous plaît assurez-vous, exception de capture et de vérifier le type avant force Déballer

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

Pour en toute sécurité, en utilisant if let:

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

Merci beaucoup! Ça a marché. Savez-vous pourquoi c'est? De retour dans Swift 1.2, nous n'avions pas à convertir en NSString, non? – Isuru

+0

Je ne suis pas sûr de Swift 1.2. Mais 'NSJSONSerialization' désérialise parfois la valeur numérique en nombre. Bien sûr, avant de convertir les valeurs de 'NSDecimalNumber', laissez d'abord vérifier [object class] (dynamicType). – anhtu

+0

J'ai eu la même erreur avec un cadre que j'utilisais qui lit les valeurs de configuration à partir d'un fichier plist personnalisé dans les ressources de l'ensemble (pas de JSON impliqué). J'avais défini certains des champs de plist comme 'String's, mais ils s'attendaient probablement à ce qu'ils soient des' Number's. Changer le type en 'Number' a résolu le problème. –

3

La raison de l'échec est que le JSON retourne String valeurs, pas de chiffres.

Si les données JSON renvoyées contiennent uniquement ces deux paires de valeurs de clé, déclarez le type [String:String] qui évite le cast de type.

Dans tous les cas, vous devez mettre le code pour mettre à jour les variables dans la "bonne" branche de l'expression 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

Merci pour la réponse. Mais je ne peux pas simplement faire Double (jsonDict ["totalfup"]) 'comme je reçois cette erreur. ** Impossible d'appeler l'initialiseur pour le type 'Double' avec une liste d'arguments de type '(AnyObject?)' **. Je suppose que vous devez définir le type de paires de valeurs clés comme '[String: Double]' pour que cela fonctionne. – Isuru

+0

si 'jsonDict' est casté en' [String: String] '(voir la fin de la ligne' NSJSONSerialization' dans ma réponse) le compilateur ne peut pas supposer que c'est 'AnyObject'.Cependant, j'ai oublié les points d'exclamation yo déplier les valeurs – vadian

+0

@vadian s'il vous plaît mettre à jour votre réponse, sinon il ne compilera pas ... (toutes les propriétés doivent être initialisées) – user3441734

13

Je pense que cela pourrait vous aider à

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

pourquoi ne pas utiliser les types natifs de Swift directement?

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