2015-10-23 21 views
51

このようなSwift構造体があります。'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変数のprintlnです。私はプロパティtotalDatatotalfupの値を代入しようとすると

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

、私はこのエラーを取得します。

'をするNSNumber'

誰もが知っている理由に型 'NSTaggedPointerString' の値をキャストすることができませんでしたか?私はプロパティタイプをfloatに変更しようとしましたが、その後は構造体全体をクラスに変更しようとしましたが、それでも問題は発生します。

答えて

77

エラーの理由はjsonDict["totalfup"]です。文字列であるため、StringをDoubleに変換する必要があります。

、確認してキャッチ例外とif letを使用して、力アンラップ安全のために

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

前に型をチェックしてください:

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

ありがとうございます!それはうまくいった。なぜこれが分かっていますか? Swift 1.2に戻って、私たちは 'NSString'sに変換する必要はありませんでしたか? – Isuru

+0

Swift 1.2についてはわかりません。しかし、NSJSONSerializationは数値を数値として逆直列化することがあります。確かに、NSDecimalNumberから値を変換する前に、まず[object class](dynamicType)をチェックしてください。 – anhtu

+0

バンドルのリソース(JSONは関係ありません)のカスタムplistファイルから設定値を読み取るために使用していたフレームワークで同じエラーが発生しました。私はplistフィールドのいくつかを 'String'sとして定義しましたが、APIはそれらが' Number'sであると期待していました。タイプを「番号」に変更することで問題が解決されました。 –

3

失敗の理由は、JSONはString値を返すことで、数字ではありません。

戻り値のJSONデータにこれらの2つのキー値のペアのみが含まれている場合は、タイプキャストを避けるタイプが[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)") 
     } 
    } 
} 
+0

返事をありがとう。しかし、私はこのエラーが発生したときに単に 'Double(jsonDict [" totalfup "])を実行することはできません。 **タイプ '(AnyObject?)' **の引数リストで 'Double'型の初期化子を呼び出すことはできません。私は '' [String:Double] 'としてキー値のペア型を定義しなければならないと思います。 – Isuru

+0

'jsonDict'が' [String:String] 'にキャストされている場合(私の答えの' NSJSONSerialization'行の最後を見てください)、コンパイラは 'AnyObject'を想定できません。しかし、感嘆符を忘れて、 – vadian

+0

@vadianの値をアンラップしてください。そうでなければ、コンパイルされません...(すべてのプロパティを初期化しなければなりません) – user3441734

13

私はこれがあなたに直接スウィフトのネイティブ型を使用しない理由

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

助けることができると思いますか?

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 
    */ 
} 
関連する問題